Class: ASIR::Coder::XML
Overview
!SLIDE XML
Encode/Decode objects as XML.
Defined Under Namespace
Classes: Error
Constant Summary
collapse
- CC =
'::'.freeze
- D =
'.'.freeze
- B =
'<'.freeze
- S =
' '.freeze
- E =
'>'.freeze
- SE =
'/>'.freeze
- BS =
'</'.freeze
- A =
'='.freeze
- DECODER =
{
'NilClass' => lambda { | _, dom | nil },
'TrueClass' => lambda { | _, dom | true },
'FalseClass' => lambda { | _, dom | false },
'String' => lambda { | _, dom | (dom.attributes[:v] || dom.content) },
'Symbol' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_sym },
'Integer' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_i },
'Float' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_f },
"Array" => lambda { | _, dom |
obj = [ ]
_.map_dom_id_to_obj! dom, obj
dom.each_element do | elem |
obj << _.decode_dom(elem)
end
obj
},
'Hash' => lambda { | _, dom |
obj = { }
_.map_dom_id_to_obj! dom, obj
key = nil
dom.each_element do | val |
if key
obj[_.decode_dom(key)] = _.decode_dom(val)
key = nil
else
key = val
end
end
obj
},
'Object' => lambda { | _, dom |
cls_name = dom.name
cls = _.tag_cls(cls_name)
obj = cls.allocate
_.map_dom_id_to_obj! dom, obj
dom.each_element do | child |
key = child.name
val = _.decode_dom child.first
obj.instance_variable_set("@#{key}", val)
end
obj
},
}
Instance Attribute Summary
Attributes included from Log
#_logger
Instance Method Summary
collapse
#resolve_object
Methods inherited from ASIR::Coder
#_subclass_responsibility, #decode, #encode
Methods included from Log
#_log, #_log_enabled=, #_log_enabled?, #_log_format, #_log_result, enabled, enabled=, included
#initialize
Instance Method Details
#_decode(obj) ⇒ Object
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/asir/coder/xml.rb', line 25
def _decode obj
@stream = obj
@decoder ||= DECODER; @decoder_object = nil
@dom_id_map = { }
@dom_id = 0
@cls_tag_map = { }
@parser = ::XML::Parser.string(@stream)
@dom = @parser.parse
decode_dom @dom.root
end
|
#_decode_dom(dom) ⇒ Object
141
142
143
144
145
146
147
|
# File 'lib/asir/coder/xml.rb', line 141
def _decode_dom dom
cls_name = dom.name
decoder = @decoder[cls_name] ||
(@decoder_object ||= @decoder['Object'])
raise Error, "BUG: " unless decoder
decoder.call(self, dom)
end
|
#_encode(obj) ⇒ Object
16
17
18
19
20
21
22
23
|
# File 'lib/asir/coder/xml.rb', line 16
def _encode obj
@stream = ''
@dom_id_map = { }
@dom_id = 0
@cls_tag_map = { }
encode_dom obj
@stream
end
|
#_encode_dom(obj) ⇒ Object
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/asir/coder/xml.rb', line 44
def _encode_dom obj
case obj
when NilClass, TrueClass, FalseClass
tag_obj(obj)
when Numeric
tag_obj(obj, nil, :v => obj.to_s)
when Symbol
tag_obj(obj) do
@stream << obj.to_s
end
when String
tag_obj(obj, :id) do
@stream << obj.to_s
end
when Array
tag_obj(obj, :id) do
obj.each do | elem |
encode_dom elem
end
end
when Hash
tag_obj(obj, :id) do
obj.each do | key, val |
encode_dom key
encode_dom val
end
end
else
tag_obj(obj, :id) do
obj.instance_variables.each do | attr |
val = obj.instance_variable_get(attr)
key = attr.to_s.sub(/^@/, '')
tag(key) do
encode_dom val
end
end
end
end
end
|
#cls_tag(obj) ⇒ Object
95
96
97
98
|
# File 'lib/asir/coder/xml.rb', line 95
def cls_tag obj
obj = obj.class
@cls_tag_map[obj] ||= obj.name.gsub(CC, D).freeze
end
|
#decode_dom(dom) ⇒ Object
128
129
130
131
132
133
134
135
136
137
138
139
|
# File 'lib/asir/coder/xml.rb', line 128
def decode_dom dom
if dom_id = dom.attributes[:idref]
unless obj = @dom_id_map[dom_id]
raise Error::BadIdref, "in element #{dom}"
end
obj
else
obj = _decode_dom(dom)
map_dom_id_to_obj! dom, obj if dom.attributes[:id]
obj
end
end
|
#encode_dom(obj) ⇒ Object
36
37
38
39
40
41
42
|
# File 'lib/asir/coder/xml.rb', line 36
def encode_dom obj
if dom_id = @dom_id_map[obj.object_id]
tag_obj(obj, nil, :idref => dom_id.first)
else
_encode_dom obj
end
end
|
#map_dom_id_to_obj!(dom, obj) ⇒ Object
195
196
197
198
199
200
201
202
203
|
# File 'lib/asir/coder/xml.rb', line 195
def map_dom_id_to_obj! dom, obj
dom_id = dom.attributes[:id]
debugger unless dom_id
raise Error, "no :id attribute in #{dom}" unless dom_id
if (other_obj = @dom_id_map[dom_id]) and other_obj.object_id != obj.object_id
raise Error, "BUG: :id #{dom_id} already used for #{other_obj.class.name} #{other_obj.inspect}"
end
@dom_id_map[dom_id] = obj
end
|
#map_obj_to_dom_id!(obj) ⇒ Object
100
101
102
103
104
105
106
107
|
# File 'lib/asir/coder/xml.rb', line 100
def map_obj_to_dom_id! obj
if dom_id = @dom_id_map[obj.object_id]
dom_id.first
else
@dom_id_map[obj.object_id] = [ @dom_id += 1, obj ]
@dom_id
end
end
|
#prepare ⇒ Object
211
|
# File 'lib/asir/coder/xml.rb', line 211
def prepare; dup; end
|
#tag(tag, attrs = nil) ⇒ Object
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'lib/asir/coder/xml.rb', line 111
def tag tag, attrs = nil
tag = tag.to_s
@stream << B << tag << S
if attrs
attrs.each do | key, val |
@stream << key.to_s << A << val.to_s.inspect << S
end
end
if block_given?
@stream << E; yield; @stream << BS << tag << E
else
@stream << SE
end
end
|
#tag_cls(cls_name) ⇒ Object
206
207
208
|
# File 'lib/asir/coder/xml.rb', line 206
def tag_cls cls_name
@cls_tag_map[cls_name.freeze] ||= resolve_object(cls_name.gsub('.', '::'))
end
|
#tag_obj(obj, with_id = false, attrs = nil) ⇒ Object
84
85
86
87
88
89
90
91
92
|
# File 'lib/asir/coder/xml.rb', line 84
def tag_obj obj, with_id = false, attrs = nil
if block_given?
tag(cls_tag(obj), with_id ? { with_id => map_obj_to_dom_id!(obj) } : nil) do
yield
end
else
tag(cls_tag(obj), attrs)
end
end
|