<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def ProcessEvent( self, event, parser_chain=None, file_entry=None, query=None):
 """Processes an event before it written to the storage. Args: event (EventObject|EventData):
 event or event data. parser_chain (Optional[str]):
 parsing chain up to this point. file_entry (Optional[dfvfs.FileEntry]):
 file entry, where None will use the current file entry set in the mediator. query (Optional[str]):
 query that was used to obtain the event. Raises: KeyError: if there's an attempt to add a duplicate attribute value to the event. """

    # TODO: rename this to event.parser_chain or equivalent.
    if not getattr(event, 'parser', None) and parser_chain:
      event.parser = parser_chain

    # TODO: deprecate text_prepend in favor of an event tag.
    if not getattr(event, 'text_prepend', None) and self._text_prepend:
      event.text_prepend = self._text_prepend

    if file_entry is None:
      file_entry = self._file_entry

    display_name = None
    if file_entry:
      event.pathspec = file_entry.path_spec

      if not getattr(event, 'filename', None):
        path_spec = getattr(file_entry, 'path_spec', None)
        event.filename = path_helper.PathHelper.GetRelativePathForPathSpec(
            path_spec, mount_path=self._mount_path)

      if not display_name:
        # TODO: dfVFS refactor: move display name to output since the path
        # specification contains the full information.
        display_name = self.GetDisplayName(file_entry)

      stat_object = file_entry.GetStat()
      inode_value = getattr(stat_object, 'ino', None)
      # TODO: refactor to ProcessEventData.
      # Note that we use getattr here since event can be either EventObject
      # or EventData.
      if getattr(event, 'inode', None) is None and inode_value is not None:
        event.inode = self._GetInode(inode_value)

    if not getattr(event, 'display_name', None) and display_name:
      event.display_name = display_name

    if not getattr(event, 'hostname', None) and self.hostname:
      event.hostname = self.hostname

    if not getattr(event, 'username', None):
      user_sid = getattr(event, 'user_sid', None)
      username = self._knowledge_base.GetUsernameByIdentifier(user_sid)
      if username:
        event.username = username

    if not getattr(event, 'query', None) and query:
      event.query = query

    for attribute, value in iter(self._extra_event_attributes.items()):
      if hasattr(event, attribute):
        raise KeyError('Event already has a value for {0:s}'.format(attribute))

      setattr(event, attribute, value)