roundtrip_xml 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e77511e2e2d2f257ab080cebb04b0f66ee25af7
4
- data.tar.gz: 6a3ebee19eeffa57d16e80c18a87942d58edbfe4
3
+ metadata.gz: e2a828a5eed9aa3a533c7d19e959f9dd4ff3f1fd
4
+ data.tar.gz: 26585d066af79709c1f972fa82902af574a58881
5
5
  SHA512:
6
- metadata.gz: cd50200ff25f0195d300e5c0d25ffff38dbb7ec84ce534ab0f7bf8e3a686e09eefd58f837012f8c31a695182535956753643d2c1f7fd69db46b318fc22a6dd28
7
- data.tar.gz: 872b94b1378169aafd2efcdb979c8649dbbc1d9530cebbef70dc57143bc7de41fdfc94babbddeae3e5757eb1543ca67ca8c26dfef9ff9dd6dac6838d6ffa7fc3
6
+ metadata.gz: 9d875f5ee525541bafbe6068aa54cbb186fe5b9eddef5b726bc717ccbbcabdd00435d0cd11ee98d3a7bb4e872725f9d04b02a18283a07e39b03a652ca8792742
7
+ data.tar.gz: d1f17f80df1b8d92886c81a9cd9c1b19c9cf37482144eda6075c20bce5ea76ae085ff3ca4b0370f905976b5d12b7e053a571171bd6a4a352f1414dfd5d00bc61
@@ -96,4 +96,9 @@ class BaseCleanroom
96
96
  self.class.send(:expose, name)
97
97
  end
98
98
  end
99
+
100
+ def _matcher(accessor, matcher)
101
+ @el.class.plain_accessor accessor, matcher
102
+ end
103
+ expose :_matcher
99
104
  end
@@ -34,7 +34,7 @@ class DslRuntime
34
34
  end
35
35
 
36
36
  # @param block Proc This proc is passed each health rule and must return a string value which specifies the partition for it
37
- def write_dsl(xml, root_class_name, root_method, helpers = '', &block)
37
+ def write_dsl(xml, root_class_name, root_method, helpers = nil, &block)
38
38
  roxml_root = fetch(root_class_name).from_xml xml
39
39
 
40
40
  extractor = Extractor.new roxml_root.send(root_method), self, root_class_name, helpers
@@ -83,10 +83,10 @@ class DslRuntime
83
83
 
84
84
  def evaluate_raw(dsl, root_class, templates = [], &block)
85
85
  cleanroom = RootCleanroom.new(fetch(root_class).new, self)
86
- templates.each { |t| cleanroom.evaluate_file t }
87
- if block_given?
88
- cleanroom.evaluate &block
89
- else
86
+ templates.each { |t| cleanroom.evaluate t }
87
+ if block_given?
88
+ cleanroom.evaluate &block
89
+ else
90
90
  cleanroom.evaluate dsl
91
91
  end
92
92
 
@@ -6,6 +6,7 @@ require 'set'
6
6
  require 'roundtrip_xml/utils'
7
7
  require 'multiset'
8
8
  require 'roundtrip_xml/roxml_subclass_helpers.rb'
9
+ require 'differ'
9
10
 
10
11
  class Extractor
11
12
 
@@ -13,10 +14,11 @@ class Extractor
13
14
  @roxml_objs = roxml_objs
14
15
  @runtime = runtime
15
16
  @root_class = root_class
17
+ @definitions = {}
16
18
  if block_given?
17
- @definitions = eval_definitions root_class, &block
19
+ eval_definitions root_class, &block
18
20
  else
19
- @definitions = eval_definitions root_class, definitions
21
+ definitions.each {|defin| eval_definitions root_class, defin } if definitions
20
22
  end
21
23
  end
22
24
 
@@ -29,7 +31,7 @@ class Extractor
29
31
  end
30
32
  new_names = @runtime.instance_variable_get(:@classes).keys
31
33
  def_names = new_names - old_names
32
- def_names.inject({}) do |out, name|
34
+ @definitions = def_names.inject(@definitions) do |out, name|
33
35
  clazz = @runtime.fetch(name)
34
36
  parent = get_root_class clazz
35
37
  obj = clazz.new
@@ -57,7 +59,14 @@ class Extractor
57
59
  h.delete '__class'
58
60
  end
59
61
  diffs = HashDiff.diff(obj_hash, def_hash).map do |diff|
60
- ROXMLDiff.new diff[1], from_hash(diff[2]), diff[3]
62
+ accessor_name = if diff[3].is_a?(String) && match = diff[3].match(/#{Utils::UNDEFINED_PARAM}:(\w*)/)
63
+ match[1].to_sym
64
+ end
65
+ if accessor_name && defin.class.plain_accessors.include?(accessor_name)
66
+ matcher = defin.class.plain_accessors(true)[accessor_name]
67
+ end
68
+ template_val = diff[3].is_a?(String) && accessor_name ? Utils::UndefinedParam.new(accessor_name, diff[3]) : diff[3]
69
+ ROXMLDiff.new diff[0], diff[1], from_hash(diff[2]), template_val, matcher
61
70
  end
62
71
 
63
72
  diffs
@@ -82,11 +91,11 @@ class Extractor
82
91
 
83
92
  defs.each do |defin|
84
93
  diffs = diff_definition(defin, obj)
85
- if diffs.all? {|diff| diff.template_val.is_a?(Utils::UndefinedParam) || diff.template_val == nil }
94
+ if diffs.all? {|diff| diff.operation == '~' && (diff.template_val.is_a?(Utils::UndefinedParam) || diff.template_val == nil || interpolated_diff(diff)) }
86
95
  new_obj = defin.class.new
87
96
  param_values = diffs.inject({}) do |values, diff|
88
97
  name = diff.template_val ? diff.template_val.name : diff.key
89
- values[name] = diff.obj_val
98
+ values[name] = interpolated_diff(diff) ? extract_interpolated_diff(diff) : diff.obj_val
90
99
  values
91
100
  end
92
101
  set_attributes new_obj, param_values
@@ -97,7 +106,8 @@ class Extractor
97
106
 
98
107
  obj.class.roxml_attrs.each do |a|
99
108
  if a.array?
100
- elements = obj.send(a.accessor).map {|el| convert_roxml_obj el}
109
+ elements = a.sought_type.class == Class ?
110
+ obj.send(a.accessor).map {|el| convert_roxml_obj el} : obj.send(a.accessor)
101
111
  obj.send a.setter.to_sym, elements
102
112
  elsif a.sought_type.class == Class
103
113
  current_value = obj.send(a.accessor)
@@ -107,22 +117,78 @@ class Extractor
107
117
  obj
108
118
  end
109
119
 
120
+ def interpolated_diff(diff)
121
+ diff.obj_val.is_a?(String) && diff.template_val.is_a?(Utils::UndefinedParam) && diff.template_val.original && diff.template_val.original.match(/#{Utils::UNDEFINED_PARAM}:/)
122
+ end
123
+
124
+ def extract_interpolated_diff(diff)
125
+ s_diff = Differ.diff_by_word(diff.obj_val, diff.template_val.original).to_s
126
+ value = s_diff.match(/(\{"\s*#{Utils::UNDEFINED_PARAM}:([\S]*)\s*" >> "(.*)"})/)[3]
127
+ value.strip.match(diff.matcher)[1]
128
+ end
129
+
110
130
  def set_attributes(obj, params)
111
131
  params.each do |param, val|
112
132
  methods = param.to_s.split '.'
113
- # set_deep_attribute obj, methods, val
114
- obj.send "#{param}=", val
133
+ methods << val
134
+ set_deep_attributes obj, methods
135
+ # obj.send "#{param}=", val
136
+ end
137
+
138
+ end
139
+
140
+ def set_deep_attributes(obj, methods)
141
+ index = methods[0].match(/\[(\d+)\]/)
142
+ child = index ? nil : obj.send(methods[0])
143
+ method = methods[0]
144
+ method.gsub!(/\[\d+\]/, '')
145
+ if child
146
+ set_deep_attributes child, methods[1..methods.size]
147
+ else
148
+ if index
149
+ arr = obj.send(method) || []
150
+ arr[Integer(index[1])] = methods[1..1][0] # hacky way to get second element
151
+ obj.send("#{method}=", arr)
152
+ else
153
+ obj.send(methods[0] + '=', set_deep_attributes_helper(obj, methods))
154
+ end
155
+ end
156
+ end
157
+
158
+ def set_deep_attributes_helper(obj, methods)
159
+ method = methods.shift
160
+ index = method.match(/\[(\d+)\]/)
161
+ return obj.send(method + '=', methods.first) if !index && methods.size == 1
162
+
163
+ method.gsub!(/\[\d+\]/, '')
164
+ child = obj.send(method)
165
+ unless child || methods.size == 1
166
+ clazz_name = method.dup
167
+ clazz_name[0] = clazz_name[0].upcase
168
+ child = @runtime.fetch(clazz_name.to_sym).new
169
+ obj.send("#{method}=", child)
170
+
171
+ end
172
+ if index
173
+ arr = obj.send(method) || []
174
+ arr[Integer(index[1])] = methods.first
175
+ obj.send("#{method}=", arr)
176
+ else
177
+ obj.send(method + '=', set_deep_attributes_helper(child, methods))
115
178
  end
116
179
 
180
+ child.is_a?(Array) ? obj : child || obj
117
181
  end
118
182
 
119
183
  end
120
184
 
121
185
  class ROXMLDiff
122
- attr_reader :key, :obj_val, :template_val
123
- def initialize(key, obj_val, template_val)
186
+ attr_reader :operation, :key, :obj_val, :template_val, :matcher
187
+ def initialize(operation, key, obj_val, template_val, matcher = nil)
188
+ @operation = operation
124
189
  @key = key.to_sym
125
190
  @obj_val = obj_val
126
191
  @template_val = template_val
192
+ @matcher = matcher
127
193
  end
128
194
  end
@@ -5,9 +5,9 @@ module PlainAccessors
5
5
  end
6
6
 
7
7
  module ClassMethods
8
- def plain_accessor(name, default = nil)
8
+ def plain_accessor(name, matcher = /(\S*)/)
9
9
  @plain_accessors ||= {}
10
- @plain_accessors[name] = default
10
+ @plain_accessors[name] = matcher
11
11
  attr_writer name
12
12
  define_method(name) do
13
13
  val = instance_variable_get "@#{name}"
@@ -43,11 +43,13 @@ EOF
43
43
  obj.attributes.each do |attr|
44
44
  val = obj.send attr.accessor
45
45
  next unless val
46
- # if !val || (is_subclass && obj.class.defaults.keys.include?(attr.accessor))
47
- # next
48
- # end
46
+
49
47
  if attr.sought_type.class == Symbol
50
- accessors << [:call, nil, attr.accessor, [:str, val]]
48
+ if val.is_a? Array
49
+ val.each {|v| accessors << [:call, nil, attr.accessor, [:str, v]]}
50
+ else
51
+ accessors << [:call, nil, attr.accessor, [:str, val]]
52
+ end
51
53
  elsif val.class == Array
52
54
  val.each { |v| accessors << create_sexp_for_roxml_obj(v, attr.accessor) }
53
55
  else
@@ -79,7 +81,7 @@ EOF
79
81
  sexp = Sexp.from_array s
80
82
  processor = Ruby2Ruby.new
81
83
  str = processor.process(sexp)
82
- str.gsub(/\((.*)\)/, ' \\1').gsub(/"([^'\n]+)"/, "'\\1'")
84
+ str.gsub(/([^"])\(([^\(\)]*|".*")\)([^"])([^{]|$)/, '\\1 \\2\\3\\4').gsub(/"([^'\n]+)"/, "'\\1'").gsub(/# do nothing/, '')
83
85
  end
84
86
 
85
87
  def write_full_dsl(root_method)
@@ -7,11 +7,16 @@ def name_to_sym_helper(name, lower_case = false)
7
7
  new_name.to_sym
8
8
  end
9
9
  module Utils
10
- # UNDEFINED_PARAM = 'UNDEFINED_PARAM_VALUE'
10
+ UNDEFINED_PARAM = 'UNDEFINED_PARAM'.freeze
11
11
  class UndefinedParam
12
- attr_reader :name
13
- def initialize(name)
12
+ attr_reader :name, :original
13
+ def initialize(name, original = nil)
14
14
  @name = name
15
+ @original = original
16
+ end
17
+
18
+ def to_s
19
+ "#{Utils::UNDEFINED_PARAM}:#{@name}"
15
20
  end
16
21
  end
17
22
 
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.2.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Usick
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: differ
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.1'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.1'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: multiset
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
189
  version: '0'
176
190
  requirements: []
177
191
  rubyforge_project:
178
- rubygems_version: 2.4.6
192
+ rubygems_version: 2.4.8
179
193
  signing_key:
180
194
  specification_version: 4
181
195
  summary: DSL which learns from XML