class PolyrexSchema
Attributes
to_a[R]
to_doc[R]
to_h[R]
to_s[R]
to_schema[R]
Public Class Methods
new(s=nil)
click to toggle source
# File lib/polyrex-schema.rb, line 12 def initialize(s=nil) if s then if s =~ /\// then s.prepend 'root/' if s[0] == '{' r = add_node split(s) r[3] << node('recordx_type', 'polyrex') @doc = Rexle.new(r) @to_a = scan_to_a(@doc.root.xpath 'records/*') @to_h = scan_to_h(@doc.root.xpath 'records/*') @to_doc = @doc @to_s = @doc.to_s else a = [s[/^[^\[]+/], *s[/(?<=\[)[^\]]+/].split(/ *, */)].map(&:to_sym) @to_a = [a] h2 = { format_mask: a[1..-1].map {|x| "[!%s]" % x }.join(' '), schema: "%s[%s]" % [a[0], a[1..-1].join(', ')], recordx_type: 'polyrex' } h = {a[0] => {summary: a[1..-1]\ .zip(Array.new(a.length-1)).to_h.merge(h2), records: nil }} @to_doc = Rexle.new(RexleBuilder.new(h, debug: false).to_a) end end end
Public Instance Methods
parse(s)
click to toggle source
# File lib/polyrex-schema.rb, line 49 def parse(s) doc = Rexle.new s @to_schema = scan_to_schema doc.root self end
Private Instance Methods
add_node(a)
click to toggle source
# File lib/polyrex-schema.rb, line 62 def add_node(a) return if a.empty? schema = a.join('/') line = a.shift raw_siblings = line[/\{.*/] if raw_siblings then return split(raw_siblings[1..-2],';').map {|x| add_node split(x) + a} end name, raw_fields = line.split('[',2) rows = if raw_fields then fields = raw_fields.chop.split(',') field_rows = fields.map {|field| node(field.strip) } field_rows << node('schema', schema) field_rows << node('format_mask', fields.map{|x| "[!%s]" % x.strip}\ .join(' ')) end children = add_node(a) children = [children] if children and children[0].is_a? String node(name, '', node('summary', '', *rows), node('records', '', *children) ) end
node(name, val='', *children)
click to toggle source
# File lib/polyrex-schema.rb, line 58 def node(name, val='', *children) [name, {}, val, *children] end
scan_to_a(nodes)
click to toggle source
# File lib/polyrex-schema.rb, line 93 def scan_to_a(nodes) nodes.map do |r| a = r.xpath('summary/*/name()') # => ["entry", "format_mask"] fields = (a - %w(schema format_mask)).map(&:to_sym) node = r.xpath 'records/*' if node.any? then children = scan_to_a(node) [r.name.to_sym, *fields, children] else [r.name.to_sym, *fields] end end end
scan_to_h(nodes)
click to toggle source
# File lib/polyrex-schema.rb, line 111 def scan_to_h(nodes) nodes.map do |r| a = r.xpath('summary/*/name()') # => ["entry", "format_mask"] schema = r.text('summary/schema') fields = (a - %w(schema format_mask)).map(&:to_sym) node = r.xpath 'records/*' if node.any? then children = scan_to_h(node) {name: r.name.to_sym, fields: fields, schema: schema, children: children} else {name: r.name.to_sym, fields: fields, schema: schema} end end end
scan_to_schema(node)
click to toggle source
# File lib/polyrex-schema.rb, line 130 def scan_to_schema(node) e = node.element('summary') fields = e.elements.map(&:name) - %w(schema recordx_type format_mask) recs = node.xpath('records/*') summary = fields.any? ? ("[%s]" % fields.join(', ')) : '' records = recs.any? ? '/' + recs\ .uniq {|x| x.name <=> x.name}.map {|x| scan_to_schema(x)}.join('/') : '' node.name + summary + records end
split(s, separator='/')
click to toggle source
splits into levels identified by a slash (/) or a semicolon (;)
# File lib/polyrex-schema.rb, line 145 def split(s, separator='/') brace_count = 0 s.each_char.inject(['']) do |r, c| case c when '{' brace_count += 1 when '}' brace_count -= 1 end if c != separator or brace_count > 0 then r.last << c else c = '' if c == separator r << c end r end end