#
# Тест парсинга файлов, в которых каждая строка содержит один из следующих
# тегов:
#
# {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
Generated with the Darkfish Rdoc Generator 2.