def _ParseUSNChangeJournal(self, parser_mediator, usn_change_journal):
    """Parses an USN change journal.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfvfs.
      usn_change_journal (pyfsntsfs.usn_change_journal): USN change journal.

    Raises:
      ParseError: if an USN change journal record cannot be parsed.
    """
    if not usn_change_journal:
      return

    usn_record_map = self._GetDataTypeMap('usn_record_v2')

    usn_record_data = usn_change_journal.read_usn_record()
    while usn_record_data:
      current_offset = usn_change_journal.get_offset()

      try:
        usn_record = self._ReadStructureFromByteStream(
            usn_record_data, current_offset, usn_record_map)
      except (ValueError, errors.ParseError) as exception:
        raise errors.ParseError((
            'Unable to parse USN record at offset: 0x{0:08x} with error: '
            '{1!s}').format(current_offset, exception))

      # Per MSDN we need to use name offset for forward compatibility.
      name_offset = usn_record.name_offset - 60
      utf16_stream = usn_record.name[name_offset:usn_record.name_size]

      try:
        name_string = utf16_stream.decode('utf-16-le')
      except (UnicodeDecodeError, UnicodeEncodeError) as exception:
        name_string = utf16_stream.decode('utf-16-le', errors='replace')
        parser_mediator.ProduceExtractionWarning((
            'unable to decode USN record name string with error: '
            '{0:s}. Characters that cannot be decoded will be replaced '
            'with "?" or "\\ufffd".').format(exception))

      event_data = NTFSUSNChangeEventData()
      event_data.file_attribute_flags = usn_record.file_attribute_flags
      event_data.file_reference = usn_record.file_reference
      event_data.filename = name_string
      event_data.offset = current_offset
      event_data.parent_file_reference = usn_record.parent_file_reference
      event_data.update_reason_flags = usn_record.update_reason_flags
      event_data.update_sequence_number = usn_record.update_sequence_number
      event_data.update_source_flags = usn_record.update_source_flags

      if not usn_record.update_date_time:
        date_time = dfdatetime_semantic_time.SemanticTime('Not set')
      else:
        date_time = dfdatetime_filetime.Filetime(
            timestamp=usn_record.update_date_time)

      event = time_events.DateTimeValuesEvent(
          date_time, definitions.TIME_DESCRIPTION_ENTRY_MODIFICATION)
      parser_mediator.ProduceEventWithEventData(event, event_data)

      usn_record_data = usn_change_journal.read_usn_record()
Parses an USN change journal.

    Args:
      parser_mediator (ParserMediator): mediates interactions between parsers
          and other components, such as storage and dfvfs.
      usn_change_journal (pyfsntsfs.usn_change_journal): USN change journal.

    Raises:
      ParseError: if an USN change journal record cannot be parsed.