Class Index [+]

Quicksearch
#
# Тест парсинга файлов, в которых каждая строка содержит один из следующих
# тегов:
#
#   {sent-sms {timestamp <str>} {cprov <str>} {trx-id <str>} {op-id <str>} {msisdn <str>} {message-id <str>} }
#   {incoming-sms {timestamp <str>} {op-id <str>} {msisdn <str>} {dest-addr <str>} {trx-id <str>} }
#   {routed {timestamp <str>} {op-id <str>} {trx-id <str>} {recipient-trx-id <str>} {cprov <str>} }
#   {delivery-receipt {timestamp <str>} {op-id <str>} {message-id <str>} {status <uint>} {trx-id <str>} }
#
# Каждый тег обязательно записывается в одну строку -- это механизм защиты от
# сбоев при записи файла -- если строка записана не полностью, то она просто
# игнорируется при чтении.
#
# Пример считывает все строки из ARGF и:
# * подсчитывает общее количество строк;
# * подсчитывает количество строк с каждым из типов тегов.
#

require 'cls-ruby'
require 'cls-ruby/tag_no_value'
require 'cls-ruby/tag_scalar'

# Класс тега SentSms.
class TagSentSms < ClsRuby::TagNoValue
  mandatory_child_tag :timestamp, ClsRuby::TagStringScalar

  mandatory_child_tag :cprov, ClsRuby::TagStringScalar

  mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
      :name => 'trx-id'

  mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
      :name => 'op-id'

  mandatory_child_tag :msisdn, ClsRuby::TagStringScalar

  mandatory_child_tag :message_id, ClsRuby::TagStringScalar,
      :name => 'message-id'

  default_tag_params :name => 'sent-sms'
end

# Класс тега incoming-sms.
class TagIncomingSms < ClsRuby::TagNoValue
  mandatory_child_tag :timestamp, ClsRuby::TagStringScalar

  mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
      :name => 'trx-id'

  mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
      :name => 'op-id'

  mandatory_child_tag :msisdn, ClsRuby::TagStringScalar

  mandatory_child_tag :dest_addr, ClsRuby::TagStringScalar,
      :name => 'dest-addr'

  default_tag_params :name => 'incoming-sms'
end

# Класс тега routed.
class TagRoutedSms < ClsRuby::TagNoValue
  mandatory_child_tag :timestamp, ClsRuby::TagStringScalar      

  mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
      :name => 'trx-id'

  mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
      :name => 'op-id'

  mandatory_child_tag :recipient_trx_id, ClsRuby::TagStringScalar,
      :name => 'recipient-trx-id'

  mandatory_child_tag :cprov, ClsRuby::TagStringScalar

  default_tag_params :name => 'routed'
end

# Класс тега delivery-receipt.
class TagDeliveryReceipt < ClsRuby::TagNoValue
  mandatory_child_tag :timestamp, ClsRuby::TagStringScalar

  mandatory_child_tag :trx_id, ClsRuby::TagStringScalar,
      :name => 'trx-id'

  mandatory_child_tag :op_id, ClsRuby::TagStringScalar,
      :name => 'op-id'

  mandatory_child_tag :message_id, ClsRuby::TagStringScalar,
      :name => 'message-id'

  mandatory_child_tag :status, ClsRuby::TagUintScalar

  default_tag_params :name => 'delivery-receipt'
end

class LineParser
  attr_reader :stats

  def initialize
    @stats = {
        :lines => 0,
        :processed => 0,
        :sent => 0,
        :incoming => 0,
        :routed => 0,
        :delivery => 0 }

    @tag_sent = TagSentSms.new( {} )
    @tag_incoming = TagIncomingSms.new( {} )
    @tag_routed = TagRoutedSms.new( {} )
    @tag_delivery = TagDeliveryReceipt.new( {} )

    @all_tags = [
        @tag_sent,
        @tag_incoming,
        @tag_routed,
        @tag_delivery ]

    @tags_and_stats_keys = {
        :sent => @tag_sent,
        :incoming => @tag_incoming,
        :routed => @tag_routed,
        :delivery => @tag_delivery }
  end

  def next_line( line )
    @stats[ :lines ] += 1
    begin
      ClsRuby::parse_string( line, *@all_tags )
      @stats[ :processed ] += 1

      detect_defined_tag
    rescue Exception => x
      $stderr.puts "Exception caught: #{x.message}\n" +
          "Stacktrace:\n" + '-'*30 + "\n#{x.backtrace.join("\n")}\n" +
          '-'*30 + "\n" +
          "Problematic line (number #{@stats[:lines]}):\n" + line

      # В случае ошибки мы не знаем, какой именно тег разбирался,
      # поэтому операцию reset нужно вызывать для всех тегов.
      @all_tags.each do |tag| tag.tag_reset end
    end
  end

private
  def detect_defined_tag
    @tags_and_stats_keys.each_pair do |key, tag|
      if tag.tag_defined?
        @stats[ key ] += 1
        tag.tag_reset
        break
      end
    end
  end
end

parser = LineParser.new
ARGF.each do |line|
  parser.next_line( line )
end

p parser.stats

# vim:ts=2:sts=2:sw=2:expandtab:ft=txt:tw=78

[Validate]

Generated with the Darkfish Rdoc Generator 2.