roundtrip_xml 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/roundtrip_xml.rb +4 -0
- data/lib/roundtrip_xml/base_cleanroom.rb +4 -11
- data/lib/roundtrip_xml/dsl_runtime.rb +133 -6
- data/lib/roundtrip_xml/extractor.rb +81 -0
- data/lib/roundtrip_xml/plain_accessors.rb +10 -6
- data/lib/roundtrip_xml/roxml_builder.rb +6 -19
- data/lib/roundtrip_xml/roxml_subclass_helpers.rb +11 -0
- data/lib/roundtrip_xml/sexp_dsl_builder.rb +108 -0
- data/lib/roundtrip_xml/utils.rb +53 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5d0171291e731011fc69e726421dc68b3ceb039
|
4
|
+
data.tar.gz: 1aaaa7152a29b616cbfd7e43b003ccf1b625ffa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de71838561d98d183d2e83b2a0311cd3db0c66f89911771ba8ea90a954b9d9ad7d6aa97e14cfd8b5aac6a78a4f5f34c13b56e7825aebac5496f866c63fb6a42a
|
7
|
+
data.tar.gz: bf4e7a4d49cccafad9ec1c21a4953bd9ccc9dd7b5eca652b8cdb65daecc0b04deafbcf3b5aa18000fa7342c0dc2babcf28a33ab45db1bfc6685471de0f5e24b3
|
data/lib/roundtrip_xml.rb
CHANGED
@@ -4,3 +4,7 @@ require './lib/roundtrip_xml/base_cleanroom'
|
|
4
4
|
require './lib/roundtrip_xml/root_cleanroom'
|
5
5
|
require './lib/roundtrip_xml/roxml_builder'
|
6
6
|
require './lib/roundtrip_xml/plain_accessors'
|
7
|
+
require './lib/roundtrip_xml/utils'
|
8
|
+
require './lib/roundtrip_xml/extractor'
|
9
|
+
require './lib/roundtrip_xml/roxml_subclass_helpers'
|
10
|
+
require './lib/roundtrip_xml/sexp_dsl_builder'
|
@@ -53,27 +53,20 @@ class BaseCleanroom
|
|
53
53
|
plain_accessors = @el.class.plain_accessors
|
54
54
|
hash = {}
|
55
55
|
@value_holder ||= {}
|
56
|
-
|
57
|
-
hash = plain_accessors.inject({}) {|h, a| h[a] = @el.send(a); h}
|
58
|
-
end
|
56
|
+
hash = plain_accessors.inject({}) {|h, a| h[a] = @el.send(a); h}
|
59
57
|
child = @runtime.create_cleanroom(clazz)
|
60
58
|
child.inherit_properties @value_holder.merge(hash)
|
61
|
-
|
59
|
+
|
62
60
|
child.evaluate &block
|
63
61
|
child.evaluate &child.get_el.process if child.get_el.respond_to? :process
|
64
|
-
|
65
|
-
# child.evaluate &child.get_el.class.proc if child.respond_to? :proc
|
62
|
+
|
66
63
|
child.get_el
|
67
64
|
end
|
68
65
|
|
69
66
|
def inherit_properties(props)
|
70
67
|
@value_holder = props
|
71
68
|
props.each do |name, val|
|
72
|
-
|
73
|
-
# @value_holder.send("#{arg}=".to_sym, value_holder.send(arg))
|
74
|
-
# create_method(arg) do
|
75
|
-
# @value_holder.send(arg)
|
76
|
-
# end
|
69
|
+
|
77
70
|
self.class.send(:attr_reader, name)
|
78
71
|
self.instance_variable_set("@#{name}".to_sym, val)
|
79
72
|
self.class.send(:expose, name)
|
@@ -3,26 +3,44 @@ require 'nokogiri'
|
|
3
3
|
require 'roundtrip_xml/roxml_builder'
|
4
4
|
require 'roundtrip_xml/root_cleanroom'
|
5
5
|
require 'roundtrip_xml/base_cleanroom'
|
6
|
+
require 'roundtrip_xml/utils'
|
7
|
+
require 'roundtrip_xml/sexp_dsl_builder'
|
8
|
+
require 'tree'
|
9
|
+
require 'set'
|
6
10
|
# Class which evaluates DSL and read XML files to populate the namespace with classes
|
7
11
|
class DslRuntime
|
12
|
+
include Utils
|
8
13
|
def initialize()
|
9
14
|
@classes = {}
|
15
|
+
@root_classes = Set.new
|
10
16
|
end
|
11
|
-
def populate(files)
|
12
|
-
files.
|
17
|
+
def populate(files, root_method=nil)
|
18
|
+
files.map {|f| populate_from_file f, root_method }
|
13
19
|
end
|
14
20
|
|
15
|
-
def populate_from_file (file)
|
16
|
-
populate_raw File.read(file)
|
21
|
+
def populate_from_file (file, root_method=nil)
|
22
|
+
populate_raw File.read(file), root_method
|
17
23
|
|
18
24
|
end
|
19
25
|
|
20
|
-
def populate_raw (raw)
|
26
|
+
def populate_raw (raw, root_method = nil)
|
21
27
|
builder = RoxmlBuilder.new (Nokogiri::XML(raw).root), @classes
|
22
28
|
new_classes = builder.build_classes
|
29
|
+
@root_classes << builder.root_class_name
|
23
30
|
@classes.merge! new_classes
|
24
|
-
|
31
|
+
if root_method
|
32
|
+
roxml_root = fetch(builder.root_class_name).from_xml raw
|
33
|
+
|
34
|
+
extractor = Extractor.new roxml_root.send(root_method), self
|
25
35
|
|
36
|
+
new_objs = extractor.convert_roxml_objs
|
37
|
+
subclasses = extractor.subclasses
|
38
|
+
roxml_root.send("#{root_method}=", new_objs)
|
39
|
+
builder = SexpDslBuilder.new [roxml_root], subclasses, self
|
40
|
+
|
41
|
+
builder.write_roxml_objs
|
42
|
+
end
|
43
|
+
end
|
26
44
|
|
27
45
|
def fetch(class_name)
|
28
46
|
@classes[class_name]
|
@@ -47,7 +65,116 @@ class DslRuntime
|
|
47
65
|
def fetch_cleanroom(root_class)
|
48
66
|
BaseCleanroom.new(fetch(root_class).new, self)
|
49
67
|
end
|
68
|
+
|
50
69
|
def create_cleanroom(root_class)
|
51
70
|
BaseCleanroom.new(root_class.new, self)
|
52
71
|
end
|
72
|
+
|
73
|
+
def marshal_dump
|
74
|
+
classes = @classes.inject({}) do |hash, (name, clazz)|
|
75
|
+
hash[name] = {xml_name: clazz.tag_name }
|
76
|
+
hash[name][:attrs] = clazz.roxml_attrs.map do |accessor|
|
77
|
+
type = accessor.sought_type.class == Class ?
|
78
|
+
accessor.sought_type.class_name : accessor.sought_type
|
79
|
+
from = accessor.sought_type == :attr ? "@#{accessor.name}" : accessor.name
|
80
|
+
{
|
81
|
+
name: accessor.accessor,
|
82
|
+
opts: {
|
83
|
+
as: accessor.array? ? [type] : type,
|
84
|
+
from: from
|
85
|
+
}
|
86
|
+
}
|
87
|
+
end
|
88
|
+
hash
|
89
|
+
end
|
90
|
+
|
91
|
+
{
|
92
|
+
root_classes: @root_classes,
|
93
|
+
classes: classes
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def deserialize_class(node, config)
|
98
|
+
clazz = fetch(node.name) || new_roxml_class(config[:xml_name])
|
99
|
+
config[:attrs].each do |attr|
|
100
|
+
type_is_parent = node.parentage && node.parentage.any? {|n| n.name == attr[:opts][:as]}
|
101
|
+
if type_is_parent
|
102
|
+
add_unprocessed_attr attr, clazz
|
103
|
+
else
|
104
|
+
clazz.xml_accessor attr[:name], transform_accessor_opts(attr[:opts])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
clazz
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_unprocessed_attr(attr_config, clazz)
|
111
|
+
@unprocessed_attrs ||= []
|
112
|
+
@unprocessed_attrs << AttrJob.new(attr_config, clazz)
|
113
|
+
end
|
114
|
+
|
115
|
+
def transform_accessor_opts(opts)
|
116
|
+
attr_type = opts[:as]
|
117
|
+
is_array = attr_type.class == Array
|
118
|
+
type = is_array ? attr_type.first : attr_type
|
119
|
+
if is_array
|
120
|
+
opts[:as] = [fetch(type)]
|
121
|
+
else
|
122
|
+
opts[:as] = fetch type
|
123
|
+
end
|
124
|
+
opts
|
125
|
+
end
|
126
|
+
|
127
|
+
def marshal_load(data)
|
128
|
+
initialize
|
129
|
+
@root_classes.merge data[:root_classes]
|
130
|
+
trees = @root_classes.map {|clazz| hash_to_tree data[:classes], clazz}
|
131
|
+
trees.each do |tree|
|
132
|
+
tree.postordered_each do |node|
|
133
|
+
@classes[node.name] = deserialize_class(node, node.content)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
@unprocessed_attrs.each do |job|
|
137
|
+
clazz = job.class
|
138
|
+
config = job.config
|
139
|
+
clazz.xml_accessor config[:name], transform_accessor_opts(config[:opts])
|
140
|
+
end if @unprocessed_attrs
|
141
|
+
end
|
142
|
+
|
143
|
+
def hash_to_tree(hash, root_name, processed = [])
|
144
|
+
node = Tree::TreeNode.new(root_name, hash[root_name])
|
145
|
+
processed << root_name
|
146
|
+
children = child_classes(hash, hash[root_name])
|
147
|
+
children.each do |name|
|
148
|
+
node << hash_to_tree(hash, name, processed) unless processed.include? name
|
149
|
+
end
|
150
|
+
node
|
151
|
+
end
|
152
|
+
|
153
|
+
def child_classes(hash, config)
|
154
|
+
config[:attrs].map do |attr|
|
155
|
+
attr_type = attr[:opts][:as]
|
156
|
+
type = attr_type.class == Array ? attr_type.first : attr_type
|
157
|
+
type if hash.key? type
|
158
|
+
end.compact
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
def serialize(path)
|
163
|
+
file = File.new path, 'w'
|
164
|
+
Marshal.dump self, file
|
165
|
+
file.close
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.load(path)
|
169
|
+
file = File.open path, 'r'
|
170
|
+
Marshal.load file
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class AttrJob
|
175
|
+
attr_accessor :class, :config
|
176
|
+
def initialize(config, clazz)
|
177
|
+
self.config = config
|
178
|
+
self.class = clazz
|
179
|
+
end
|
53
180
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'roxml'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'roundtrip_xml/utils'
|
4
|
+
require 'hashdiff'
|
5
|
+
require 'set'
|
6
|
+
require 'roundtrip_xml/utils'
|
7
|
+
require 'multiset'
|
8
|
+
require 'roundtrip_xml/roxml_subclass_helpers.rb'
|
9
|
+
|
10
|
+
class Extractor
|
11
|
+
include Utils
|
12
|
+
attr_reader :subclasses
|
13
|
+
def initialize(roxml_objs, runtime)
|
14
|
+
@roxml_objs = roxml_objs
|
15
|
+
@hashes = @roxml_objs.map { |obj| obj.to_hash }
|
16
|
+
@runtime = runtime
|
17
|
+
@subclass_names = Multiset.new
|
18
|
+
@subclasses = []
|
19
|
+
end
|
20
|
+
def list_diffs
|
21
|
+
|
22
|
+
HashDiff.best_diff(@hashes[0], @hashes[6]).sort_by do |diff|
|
23
|
+
m = diff[1].match(/\./)
|
24
|
+
m ? m.size : 0
|
25
|
+
end.map {|diff| diff[1]}
|
26
|
+
end
|
27
|
+
|
28
|
+
def similar_fields
|
29
|
+
keys = Set.new @hashes[0].keys
|
30
|
+
diff_keys = Set.new
|
31
|
+
@hashes.each do |hash_1|
|
32
|
+
@hashes.each do |hash_2|
|
33
|
+
diffs = HashDiff.best_diff(hash_1, hash_2).map do |diff|
|
34
|
+
diff[1].match(/(\w+)\.?/)[1]
|
35
|
+
end
|
36
|
+
diff_keys.merge diffs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
keys = keys - diff_keys
|
40
|
+
key_hash = keys.inject({}) do |hash, key|
|
41
|
+
hash[key] = @hashes[0][key]
|
42
|
+
hash
|
43
|
+
end
|
44
|
+
[key_hash, diff_keys]
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_romxl_class(keys, parent)
|
48
|
+
@subclass_names << parent
|
49
|
+
name = "#{parent.to_s}#{@subclass_names.count(parent)}"
|
50
|
+
clazz = new_roxml_class name, @runtime.fetch(parent) do
|
51
|
+
include RoxmlSubclassHelpers
|
52
|
+
end
|
53
|
+
clazz.defaults = keys
|
54
|
+
@runtime.add_class name, clazz
|
55
|
+
@subclasses << clazz
|
56
|
+
name
|
57
|
+
end
|
58
|
+
|
59
|
+
def convert_roxml(obj, keys, class_name)
|
60
|
+
parent = @runtime.fetch(class_name)
|
61
|
+
new = parent.new
|
62
|
+
parent.plain_accessors.each do |new_accessor|
|
63
|
+
old_accessor = new_accessor.to_s.gsub(VAR_SUFIX, '').to_sym
|
64
|
+
new.send "#{new_accessor}=", obj.send(old_accessor)
|
65
|
+
end
|
66
|
+
|
67
|
+
keys.each do |accessor|
|
68
|
+
new.send "#{accessor}=", obj.send(accessor)
|
69
|
+
end
|
70
|
+
new
|
71
|
+
end
|
72
|
+
|
73
|
+
def convert_roxml_objs
|
74
|
+
fields, diff_keys = similar_fields
|
75
|
+
parent_name = @roxml_objs[0].class.class_name
|
76
|
+
name = create_romxl_class fields, parent_name
|
77
|
+
@roxml_objs.map do |roxml|
|
78
|
+
convert_roxml roxml, diff_keys, name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -4,14 +4,18 @@ module PlainAccessors
|
|
4
4
|
end
|
5
5
|
|
6
6
|
module ClassMethods
|
7
|
-
def plain_accessor(name)
|
8
|
-
@plain_accessors ||=
|
9
|
-
@plain_accessors
|
10
|
-
|
7
|
+
def plain_accessor(name, default = nil)
|
8
|
+
@plain_accessors ||= {}
|
9
|
+
@plain_accessors[name] = default
|
10
|
+
attr_writer name
|
11
|
+
define_method(name) do
|
12
|
+
instance_variable_get "@#{name}" || @plain_accessors[name]
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
|
-
def plain_accessors
|
14
|
-
@plain_accessors ||
|
16
|
+
def plain_accessors(hash = false)
|
17
|
+
return @plain_accessors || {} if hash
|
18
|
+
(@plain_accessors && @plain_accessors.keys) || []
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# require 'roxml'
|
2
2
|
require 'nokogiri'
|
3
|
-
require 'roundtrip_xml/
|
3
|
+
require 'roundtrip_xml/utils'
|
4
4
|
# Builds dynamic classes based on an XML file.
|
5
5
|
# Classes that already exist in the DslRuntime instance are modified if necessary, not overridden.
|
6
6
|
class RoxmlBuilder
|
7
|
+
include Utils
|
7
8
|
def initialize (root, current_classes = {})
|
8
9
|
# @type Nokogiri::Element
|
9
10
|
@root = root
|
@@ -11,21 +12,15 @@ class RoxmlBuilder
|
|
11
12
|
# @type Map<Symbol, ROXML>
|
12
13
|
@generated_classes = current_classes
|
13
14
|
|
14
|
-
@root_class = @generated_classes[name_to_sym(root.name)] ||
|
15
|
-
include ROXML
|
16
|
-
include PlainAccessors
|
17
|
-
xml_convention :dasherize
|
18
|
-
xml_name root.name
|
19
|
-
def attributes
|
20
|
-
self.class.roxml_attrs
|
21
|
-
end
|
22
|
-
end
|
15
|
+
@root_class = @generated_classes[name_to_sym(root.name)] || new_roxml_class(@root.name)
|
23
16
|
|
24
17
|
@generated_classes[ name_to_sym(@root.name)] = @root_class
|
25
18
|
@nodes = {}
|
26
19
|
end
|
20
|
+
def root_class_name
|
21
|
+
name_to_sym @root.name
|
22
|
+
end
|
27
23
|
def build_classes
|
28
|
-
# @root_class.xml_name (@root.name)
|
29
24
|
@root.attributes.values.to_a.concat(@root.children.to_a).each do |child|
|
30
25
|
default_opts = {from:child.name}
|
31
26
|
if is_leaf_element?(child)
|
@@ -46,14 +41,6 @@ class RoxmlBuilder
|
|
46
41
|
@generated_classes
|
47
42
|
end
|
48
43
|
|
49
|
-
def name_to_sym(name, lower_case = false)
|
50
|
-
# name.gsub('-', '_').to_sym
|
51
|
-
new_name = name.split('-').collect(&:capitalize).join
|
52
|
-
new_name[0] = new_name[0].downcase! if lower_case
|
53
|
-
new_name.to_sym
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
44
|
def add_accessor(name, opts = {}, node)
|
58
45
|
attrs = @root_class.roxml_attrs
|
59
46
|
attr = attrs.find do |a|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# require 'rubygems'
|
2
|
+
require 'ruby2ruby'
|
3
|
+
require 'ruby_parser'
|
4
|
+
require 'pp'
|
5
|
+
require 'sexp_processor'
|
6
|
+
|
7
|
+
class SexpDslBuilder
|
8
|
+
def exp
|
9
|
+
rub = <<EOF
|
10
|
+
bar 'adf'
|
11
|
+
foo do
|
12
|
+
a "a" do
|
13
|
+
a1 1
|
14
|
+
a2 2
|
15
|
+
end
|
16
|
+
a "a" do
|
17
|
+
a1 3
|
18
|
+
a2 4
|
19
|
+
end
|
20
|
+
b "b"
|
21
|
+
c "c"
|
22
|
+
end
|
23
|
+
EOF
|
24
|
+
|
25
|
+
# s = Sexp.from_array arr
|
26
|
+
# processor = Ruby2Ruby.new
|
27
|
+
# processor.process(s)
|
28
|
+
parser = RubyParser.new
|
29
|
+
s = parser.process(rub)
|
30
|
+
s
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :roxml_objs, :subclasses, :runtime
|
34
|
+
def initialize(roxml_objs, subclasses, runtime)
|
35
|
+
self.roxml_objs = roxml_objs
|
36
|
+
self.subclasses = subclasses
|
37
|
+
self.runtime = runtime
|
38
|
+
end
|
39
|
+
|
40
|
+
def write_def_classes
|
41
|
+
arr = []
|
42
|
+
subclasses.each do |clazz|
|
43
|
+
defaults = clazz.defaults.map do |accessor, default|
|
44
|
+
[:call, nil, accessor, [:str, default]]
|
45
|
+
end
|
46
|
+
arr = [:iter,
|
47
|
+
[:call, nil, :define,
|
48
|
+
[:lit, clazz.class_name],
|
49
|
+
[:lit, clazz.superclass.class_name]
|
50
|
+
], 0, [:block, *defaults]]
|
51
|
+
end
|
52
|
+
|
53
|
+
sexp = Sexp.from_array arr
|
54
|
+
processor = Ruby2Ruby.new
|
55
|
+
processor.process(sexp)
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_sexp_for_roxml_obj(obj, root_method = nil)
|
59
|
+
is_subclass = obj.class.respond_to?(:defaults)
|
60
|
+
subclass_value = obj.class.respond_to?(:defaults) ? [:lit, obj.class.class_name] : nil
|
61
|
+
accessors = []
|
62
|
+
obj.attributes.each do |attr|
|
63
|
+
val = obj.send attr.accessor
|
64
|
+
if !val || (is_subclass && obj.class.defaults.keys.include?(attr.accessor))
|
65
|
+
next
|
66
|
+
end
|
67
|
+
if attr.sought_type.class == Symbol
|
68
|
+
accessors << [:call, nil, attr.accessor, [:str, val || '']]
|
69
|
+
elsif val.class == Array
|
70
|
+
val.each { |v| accessors << create_sexp_for_roxml_obj(v, attr.accessor) }
|
71
|
+
else
|
72
|
+
accessors << create_sexp_for_roxml_obj(val, attr.accessor) if val
|
73
|
+
end
|
74
|
+
end.compact
|
75
|
+
root_call = [:call, nil, root_method]
|
76
|
+
root_call << subclass_value if subclass_value
|
77
|
+
if root_method
|
78
|
+
[:iter, root_call,
|
79
|
+
0,
|
80
|
+
[:block, *accessors]
|
81
|
+
]
|
82
|
+
else
|
83
|
+
[:block,
|
84
|
+
*accessors]
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def write_roxml_obj(obj, root_method)
|
91
|
+
s = create_sexp_for_roxml_obj obj, root_method
|
92
|
+
|
93
|
+
sexp = Sexp.from_array s
|
94
|
+
processor = Ruby2Ruby.new
|
95
|
+
processor.process(sexp).gsub "\"", "'"
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_roxml_objs(root_method = nil)
|
99
|
+
roxml_objs.inject('') do |out, obj|
|
100
|
+
out += write_roxml_obj obj, root_method
|
101
|
+
out += "\n\n"
|
102
|
+
out
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'roxml'
|
2
|
+
require 'roundtrip_xml/plain_accessors'
|
3
|
+
require 'set'
|
4
|
+
def name_to_sym_helper(name, lower_case = false)
|
5
|
+
new_name = name.split('-').collect(&:capitalize).join
|
6
|
+
new_name[0] = new_name[0].downcase! if lower_case
|
7
|
+
new_name.to_sym
|
8
|
+
end
|
9
|
+
module Utils
|
10
|
+
|
11
|
+
VAR_SUFIX = '_v'.freeze
|
12
|
+
def self.included(base)
|
13
|
+
unless base.const_defined?(:VAR_SUFIX)
|
14
|
+
base.const_set :VAR_SUFIX, Utils::VAR_SUFIX
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def new_roxml_class(name, parent = Object, &block)
|
18
|
+
Class.new(parent) do
|
19
|
+
include ROXML
|
20
|
+
include PlainAccessors
|
21
|
+
xml_convention :dasherize
|
22
|
+
xml_name name
|
23
|
+
def attributes
|
24
|
+
self.class.roxml_attrs
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.class_name
|
28
|
+
name_to_sym_helper self.tag_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_hash
|
32
|
+
attributes.inject({}) do |hash, a|
|
33
|
+
value = a.to_ref(self).to_xml(self)
|
34
|
+
value = value.to_hash if value.respond_to? :to_hash
|
35
|
+
|
36
|
+
hash[a.accessor] = value
|
37
|
+
hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def self.unique_parent_accessors
|
41
|
+
plain = Set.new(plain_accessors.map {|accessor| accessor.to_s.gsub(VAR_SUFIX, '').to_sym})
|
42
|
+
parent_accessors = Set.new(roxml_attrs.map { |attr| attr.accessor })
|
43
|
+
parent_accessors - plain
|
44
|
+
end
|
45
|
+
class_eval &block if block_given?
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def name_to_sym(name, lower_case = false)
|
51
|
+
name_to_sym_helper(name, lower_case)
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roundtrip_xml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Usick
|
@@ -77,10 +77,14 @@ files:
|
|
77
77
|
- lib/roundtrip_xml/base_cleanroom.rb
|
78
78
|
- lib/roundtrip_xml/dsl_builder.rb
|
79
79
|
- lib/roundtrip_xml/dsl_runtime.rb
|
80
|
+
- lib/roundtrip_xml/extractor.rb
|
80
81
|
- lib/roundtrip_xml/plain_accessors.rb
|
81
82
|
- lib/roundtrip_xml/root_cleanroom.rb
|
82
83
|
- lib/roundtrip_xml/roxml_builder.rb
|
83
|
-
|
84
|
+
- lib/roundtrip_xml/roxml_subclass_helpers.rb
|
85
|
+
- lib/roundtrip_xml/sexp_dsl_builder.rb
|
86
|
+
- lib/roundtrip_xml/utils.rb
|
87
|
+
homepage: https://github.com/chrisUsick/roundtrip_xml
|
84
88
|
licenses:
|
85
89
|
- MIT
|
86
90
|
metadata: {}
|