shale 0.4.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +449 -40
  5. data/exe/shaleb +30 -6
  6. data/lib/shale/adapter/json.rb +3 -3
  7. data/lib/shale/adapter/nokogiri/document.rb +97 -0
  8. data/lib/shale/adapter/nokogiri/node.rb +100 -0
  9. data/lib/shale/adapter/nokogiri.rb +17 -156
  10. data/lib/shale/adapter/ox/document.rb +90 -0
  11. data/lib/shale/adapter/ox/node.rb +97 -0
  12. data/lib/shale/adapter/ox.rb +14 -138
  13. data/lib/shale/adapter/rexml/document.rb +98 -0
  14. data/lib/shale/adapter/rexml/node.rb +99 -0
  15. data/lib/shale/adapter/rexml.rb +14 -154
  16. data/lib/shale/adapter/toml_rb.rb +34 -0
  17. data/lib/shale/error.rb +57 -2
  18. data/lib/shale/mapper.rb +61 -9
  19. data/lib/shale/mapping/descriptor/dict.rb +12 -1
  20. data/lib/shale/mapping/descriptor/xml.rb +12 -2
  21. data/lib/shale/mapping/dict.rb +26 -2
  22. data/lib/shale/mapping/xml.rb +52 -6
  23. data/lib/shale/schema/{json_compiler → compiler}/boolean.rb +1 -1
  24. data/lib/shale/schema/{json_compiler/object.rb → compiler/complex.rb} +11 -8
  25. data/lib/shale/schema/{json_compiler → compiler}/date.rb +1 -1
  26. data/lib/shale/schema/{json_compiler → compiler}/float.rb +1 -1
  27. data/lib/shale/schema/{json_compiler → compiler}/integer.rb +1 -1
  28. data/lib/shale/schema/{json_compiler → compiler}/property.rb +6 -6
  29. data/lib/shale/schema/{json_compiler → compiler}/string.rb +1 -1
  30. data/lib/shale/schema/{json_compiler → compiler}/time.rb +1 -1
  31. data/lib/shale/schema/compiler/value.rb +21 -0
  32. data/lib/shale/schema/compiler/xml_complex.rb +50 -0
  33. data/lib/shale/schema/compiler/xml_property.rb +73 -0
  34. data/lib/shale/schema/json_compiler.rb +32 -34
  35. data/lib/shale/schema/json_generator.rb +4 -6
  36. data/lib/shale/schema/xml_compiler.rb +919 -0
  37. data/lib/shale/schema/xml_generator/import.rb +2 -2
  38. data/lib/shale/schema/xml_generator.rb +11 -13
  39. data/lib/shale/schema.rb +16 -0
  40. data/lib/shale/type/complex.rb +763 -0
  41. data/lib/shale/type/value.rb +38 -9
  42. data/lib/shale/utils.rb +42 -7
  43. data/lib/shale/version.rb +1 -1
  44. data/lib/shale.rb +22 -19
  45. data/shale.gemspec +3 -3
  46. metadata +26 -17
  47. data/lib/shale/schema/json_compiler/utils.rb +0 -52
  48. data/lib/shale/schema/json_compiler/value.rb +0 -13
  49. data/lib/shale/type/composite.rb +0 -331
data/lib/shale/mapper.rb CHANGED
@@ -5,7 +5,7 @@ require_relative 'error'
5
5
  require_relative 'utils'
6
6
  require_relative 'mapping/dict'
7
7
  require_relative 'mapping/xml'
8
- require_relative 'type/composite'
8
+ require_relative 'type/complex'
9
9
 
10
10
  module Shale
11
11
  # Base class used for mapping
@@ -42,11 +42,13 @@ module Shale
42
42
  # person.to_json
43
43
  #
44
44
  # @api public
45
- class Mapper < Type::Composite
45
+ class Mapper < Type::Complex
46
+ @model = nil
46
47
  @attributes = {}
47
48
  @hash_mapping = Mapping::Dict.new
48
49
  @json_mapping = Mapping::Dict.new
49
50
  @yaml_mapping = Mapping::Dict.new
51
+ @toml_mapping = Mapping::Dict.new
50
52
  @xml_mapping = Mapping::Xml.new
51
53
 
52
54
  class << self
@@ -78,6 +80,13 @@ module Shale
78
80
  # @api public
79
81
  attr_reader :yaml_mapping
80
82
 
83
+ # Return TOML mapping object
84
+ #
85
+ # @return [Shale::Mapping::Dict]
86
+ #
87
+ # @api public
88
+ attr_reader :toml_mapping
89
+
81
90
  # Return XML mapping object
82
91
  #
83
92
  # @return [Shale::Mapping::XML]
@@ -88,16 +97,20 @@ module Shale
88
97
  # @api private
89
98
  def inherited(subclass)
90
99
  super
100
+
101
+ subclass.instance_variable_set('@model', subclass)
91
102
  subclass.instance_variable_set('@attributes', @attributes.dup)
92
103
 
93
104
  subclass.instance_variable_set('@__hash_mapping_init', @hash_mapping.dup)
94
105
  subclass.instance_variable_set('@__json_mapping_init', @json_mapping.dup)
95
106
  subclass.instance_variable_set('@__yaml_mapping_init', @yaml_mapping.dup)
107
+ subclass.instance_variable_set('@__toml_mapping_init', @toml_mapping.dup)
96
108
  subclass.instance_variable_set('@__xml_mapping_init', @xml_mapping.dup)
97
109
 
98
110
  subclass.instance_variable_set('@hash_mapping', @hash_mapping.dup)
99
111
  subclass.instance_variable_set('@json_mapping', @json_mapping.dup)
100
112
  subclass.instance_variable_set('@yaml_mapping', @yaml_mapping.dup)
113
+ subclass.instance_variable_set('@toml_mapping', @toml_mapping.dup)
101
114
 
102
115
  xml_mapping = @xml_mapping.dup
103
116
  xml_mapping.root(Utils.underscore(subclass.name || ''))
@@ -105,6 +118,15 @@ module Shale
105
118
  subclass.instance_variable_set('@xml_mapping', xml_mapping.dup)
106
119
  end
107
120
 
121
+ def model(klass = nil)
122
+ if klass
123
+ @model = klass
124
+ xml_mapping.root(Utils.underscore(@model.name))
125
+ else
126
+ @model
127
+ end
128
+ end
129
+
108
130
  # Define attribute on class
109
131
  #
110
132
  # @param [Symbol] name Name of the attribute
@@ -143,10 +165,11 @@ module Shale
143
165
 
144
166
  @attributes[name] = Attribute.new(name, type, collection, default)
145
167
 
146
- @hash_mapping.map(name.to_s, to: name)
147
- @json_mapping.map(name.to_s, to: name)
148
- @yaml_mapping.map(name.to_s, to: name)
149
- @xml_mapping.map_element(name.to_s, to: name)
168
+ @hash_mapping.map(name.to_s, to: name) unless @hash_mapping.finalized?
169
+ @json_mapping.map(name.to_s, to: name) unless @json_mapping.finalized?
170
+ @yaml_mapping.map(name.to_s, to: name) unless @yaml_mapping.finalized?
171
+ @toml_mapping.map(name.to_s, to: name) unless @toml_mapping.finalized?
172
+ @xml_mapping.map_element(name.to_s, to: name) unless @xml_mapping.finalized?
150
173
 
151
174
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
152
175
  attr_reader :#{name}
@@ -168,7 +191,7 @@ module Shale
168
191
  # attribute :age, Shale::Type::Integer
169
192
  #
170
193
  # hsh do
171
- # map 'firatName', to: :first_name
194
+ # map 'firstName', to: :first_name
172
195
  # map 'lastName', to: :last_name
173
196
  # map 'age', to: :age
174
197
  # end
@@ -177,6 +200,7 @@ module Shale
177
200
  # @api public
178
201
  def hsh(&block)
179
202
  @hash_mapping = @__hash_mapping_init.dup
203
+ @hash_mapping.finalize!
180
204
  @hash_mapping.instance_eval(&block)
181
205
  end
182
206
 
@@ -191,7 +215,7 @@ module Shale
191
215
  # attribute :age, Shale::Type::Integer
192
216
  #
193
217
  # json do
194
- # map 'firatName', to: :first_name
218
+ # map 'firstName', to: :first_name
195
219
  # map 'lastName', to: :last_name
196
220
  # map 'age', to: :age
197
221
  # end
@@ -200,6 +224,7 @@ module Shale
200
224
  # @api public
201
225
  def json(&block)
202
226
  @json_mapping = @__json_mapping_init.dup
227
+ @json_mapping.finalize!
203
228
  @json_mapping.instance_eval(&block)
204
229
  end
205
230
 
@@ -214,7 +239,7 @@ module Shale
214
239
  # attribute :age, Shale::Type::Integer
215
240
  #
216
241
  # yaml do
217
- # map 'firat_name', to: :first_name
242
+ # map 'first_name', to: :first_name
218
243
  # map 'last_name', to: :last_name
219
244
  # map 'age', to: :age
220
245
  # end
@@ -223,9 +248,34 @@ module Shale
223
248
  # @api public
224
249
  def yaml(&block)
225
250
  @yaml_mapping = @__yaml_mapping_init.dup
251
+ @yaml_mapping.finalize!
226
252
  @yaml_mapping.instance_eval(&block)
227
253
  end
228
254
 
255
+ # Define TOML mapping
256
+ #
257
+ # @param [Proc] block
258
+ #
259
+ # @example
260
+ # calss Person < Shale::Mapper
261
+ # attribute :first_name, Shale::Type::String
262
+ # attribute :last_name, Shale::Type::String
263
+ # attribute :age, Shale::Type::Integer
264
+ #
265
+ # toml do
266
+ # map 'first_name', to: :first_name
267
+ # map 'last_name', to: :last_name
268
+ # map 'age', to: :age
269
+ # end
270
+ # end
271
+ #
272
+ # @api public
273
+ def toml(&block)
274
+ @toml_mapping = @__toml_mapping_init.dup
275
+ @toml_mapping.finalize!
276
+ @toml_mapping.instance_eval(&block)
277
+ end
278
+
229
279
  # Define XML mapping
230
280
  #
231
281
  # @param [Proc] block
@@ -247,6 +297,8 @@ module Shale
247
297
  # @api public
248
298
  def xml(&block)
249
299
  @xml_mapping = @__xml_mapping_init.dup
300
+ @xml_mapping.finalize!
301
+ @xml_mapping.root('')
250
302
  @xml_mapping.instance_eval(&block)
251
303
  end
252
304
  end
@@ -40,17 +40,28 @@ module Shale
40
40
  # @param [String] name
41
41
  # @param [Symbol, nil] attribute
42
42
  # @param [Hash, nil] methods
43
+ # @param [true, false] render_nil
43
44
  #
44
45
  # @api private
45
- def initialize(name:, attribute:, methods:)
46
+ def initialize(name:, attribute:, methods:, render_nil:)
46
47
  @name = name
47
48
  @attribute = attribute
49
+ @render_nil = render_nil
48
50
 
49
51
  if methods
50
52
  @method_from = methods[:from]
51
53
  @method_to = methods[:to]
52
54
  end
53
55
  end
56
+
57
+ # Check render_nil
58
+ #
59
+ # @return [true, false]
60
+ #
61
+ # @api private
62
+ def render_nil?
63
+ @render_nil == true
64
+ end
54
65
  end
55
66
  end
56
67
  end
@@ -16,17 +16,27 @@ module Shale
16
16
  # @api private
17
17
  attr_reader :namespace
18
18
 
19
+ # Return cdata
20
+ #
21
+ # @return [true, false]
22
+ #
23
+ # @api private
24
+ attr_reader :cdata
25
+
19
26
  # Initialize instance
20
27
  #
21
28
  # @param [String] name
22
29
  # @param [Symbol, String] attribute
23
30
  # @param [Hash, nil] methods
24
31
  # @param [Shale::Mapping::XmlNamespace] namespace
32
+ # @param [true, false] cdata
33
+ # @param [true, false] render_nil
25
34
  #
26
35
  # @api private
27
- def initialize(name:, attribute:, methods:, namespace:)
28
- super(name: name, attribute: attribute, methods: methods)
36
+ def initialize(name:, attribute:, methods:, namespace:, cdata:, render_nil:)
37
+ super(name: name, attribute: attribute, methods: methods, render_nil: render_nil)
29
38
  @namespace = namespace
39
+ @cdata = cdata
30
40
  end
31
41
 
32
42
  # Return name with XML prefix
@@ -22,6 +22,7 @@ module Shale
22
22
  def initialize
23
23
  super
24
24
  @keys = {}
25
+ @finalized = false
25
26
  end
26
27
 
27
28
  # Map key to attribute
@@ -29,18 +30,41 @@ module Shale
29
30
  # @param [String] key Document's key
30
31
  # @param [Symbol, nil] to Object's attribute
31
32
  # @param [Hash, nil] using
33
+ # @param [true, false] render_nil
32
34
  #
33
35
  # @raise [IncorrectMappingArgumentsError] when arguments are incorrect
34
36
  #
35
37
  # @api private
36
- def map(key, to: nil, using: nil)
38
+ def map(key, to: nil, using: nil, render_nil: false)
37
39
  Validator.validate_arguments(key, to, using)
38
- @keys[key] = Descriptor::Dict.new(name: key, attribute: to, methods: using)
40
+ @keys[key] = Descriptor::Dict.new(
41
+ name: key,
42
+ attribute: to,
43
+ methods: using,
44
+ render_nil: render_nil
45
+ )
46
+ end
47
+
48
+ # Set the "finalized" instance variable to true
49
+ #
50
+ # @api private
51
+ def finalize!
52
+ @finalized = true
53
+ end
54
+
55
+ # Query the "finalized" instance variable
56
+ #
57
+ # @return [truem false]
58
+ #
59
+ # @api private
60
+ def finalized?
61
+ @finalized
39
62
  end
40
63
 
41
64
  # @api private
42
65
  def initialize_dup(other)
43
66
  @keys = other.instance_variable_get('@keys').dup
67
+ @finalized = false
44
68
  super
45
69
  end
46
70
  end
@@ -63,6 +63,7 @@ module Shale
63
63
  @content = nil
64
64
  @root = ''
65
65
  @default_namespace = Descriptor::XmlNamespace.new
66
+ @finalized = false
66
67
  end
67
68
 
68
69
  # Map element to attribute
@@ -76,7 +77,15 @@ module Shale
76
77
  # @raise [IncorrectMappingArgumentsError] when arguments are incorrect
77
78
  #
78
79
  # @api private
79
- def map_element(element, to: nil, using: nil, namespace: :undefined, prefix: :undefined)
80
+ def map_element(
81
+ element,
82
+ to: nil,
83
+ using: nil,
84
+ namespace: :undefined,
85
+ prefix: :undefined,
86
+ cdata: false,
87
+ render_nil: false
88
+ )
80
89
  Validator.validate_arguments(element, to, using)
81
90
  Validator.validate_namespace(element, namespace, prefix)
82
91
 
@@ -94,7 +103,9 @@ module Shale
94
103
  name: element,
95
104
  attribute: to,
96
105
  methods: using,
97
- namespace: Descriptor::XmlNamespace.new(nsp, pfx)
106
+ namespace: Descriptor::XmlNamespace.new(nsp, pfx),
107
+ cdata: cdata,
108
+ render_nil: render_nil
98
109
  )
99
110
  end
100
111
 
@@ -109,7 +120,14 @@ module Shale
109
120
  # @raise [IncorrectMappingArgumentsError] when arguments are incorrect
110
121
  #
111
122
  # @api private
112
- def map_attribute(attribute, to: nil, using: nil, namespace: nil, prefix: nil)
123
+ def map_attribute(
124
+ attribute,
125
+ to: nil,
126
+ using: nil,
127
+ namespace: nil,
128
+ prefix: nil,
129
+ render_nil: false
130
+ )
113
131
  Validator.validate_arguments(attribute, to, using)
114
132
  Validator.validate_namespace(attribute, namespace, prefix)
115
133
 
@@ -119,7 +137,9 @@ module Shale
119
137
  name: attribute,
120
138
  attribute: to,
121
139
  methods: using,
122
- namespace: Descriptor::XmlNamespace.new(namespace, prefix)
140
+ namespace: Descriptor::XmlNamespace.new(namespace, prefix),
141
+ cdata: false,
142
+ render_nil: render_nil
123
143
  )
124
144
  end
125
145
 
@@ -128,8 +148,17 @@ module Shale
128
148
  # @param [Symbol] to Object's attribute
129
149
  #
130
150
  # @api private
131
- def map_content(to:)
132
- @content = to
151
+ def map_content(to: nil, using: nil, cdata: false)
152
+ Validator.validate_arguments('content', to, using)
153
+
154
+ @content = Descriptor::Xml.new(
155
+ name: nil,
156
+ attribute: to,
157
+ methods: using,
158
+ namespace: nil,
159
+ cdata: cdata,
160
+ render_nil: false
161
+ )
133
162
  end
134
163
 
135
164
  # Set the name for root element
@@ -152,6 +181,22 @@ module Shale
152
181
  @default_namespace.prefix = prefix
153
182
  end
154
183
 
184
+ # Set the "finalized" instance variable to true
185
+ #
186
+ # @api private
187
+ def finalize!
188
+ @finalized = true
189
+ end
190
+
191
+ # Query the "finalized" instance variable
192
+ #
193
+ # @return [truem false]
194
+ #
195
+ # @api private
196
+ def finalized?
197
+ @finalized
198
+ end
199
+
155
200
  # @api private
156
201
  def initialize_dup(other)
157
202
  @elements = other.instance_variable_get('@elements').dup
@@ -159,6 +204,7 @@ module Shale
159
204
  @content = other.instance_variable_get('@content').dup
160
205
  @root = other.instance_variable_get('@root').dup
161
206
  @default_namespace = other.instance_variable_get('@default_namespace').dup
207
+ @finalized = false
162
208
 
163
209
  super
164
210
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale Boolean type
7
7
  #
8
8
  # @api private
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'utils'
3
+ require_relative '../../utils'
4
4
 
5
5
  module Shale
6
6
  module Schema
7
- class JSONCompiler
8
- # Class representing Shale's comosite type
7
+ module Compiler
8
+ # Class representing Shale's complex type
9
9
  #
10
10
  # @api private
11
- class Object
11
+ class Complex
12
12
  # Return id
13
13
  #
14
14
  # @return [String]
@@ -18,7 +18,7 @@ module Shale
18
18
 
19
19
  # Return properties
20
20
  #
21
- # @return [Array<Shale::Schema::JSONCompiler::Property>]
21
+ # @return [Array<Shale::Schema::Compiler::Property>]
22
22
  #
23
23
  # @api private
24
24
  attr_reader :properties
@@ -62,22 +62,25 @@ module Shale
62
62
 
63
63
  # Return references
64
64
  #
65
- # @return [Array<Shale::Schema::JSONCompiler::Property>]
65
+ # @return [Array<Shale::Schema::Compiler::Property>]
66
66
  #
67
67
  # @api private
68
68
  def references
69
69
  @properties
70
70
  .filter { |e| e.type.is_a?(self.class) && e.type != self }
71
71
  .uniq { |e| e.type.id }
72
+ .sort { |a, b| a.type.file_name <=> b.type.file_name }
72
73
  end
73
74
 
74
75
  # Add property to Object
75
76
  #
76
- # @param [Shale::Schema::JSONCompiler::Property] property
77
+ # @param [Shale::Schema::Compiler::Property] property
77
78
  #
78
79
  # @api private
79
80
  def add_property(property)
80
- @properties << property
81
+ unless @properties.find { |e| e.mapping_name == property.mapping_name }
82
+ @properties << property
83
+ end
81
84
  end
82
85
  end
83
86
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale Date type
7
7
  #
8
8
  # @api private
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale Float type
7
7
  #
8
8
  # @api private
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale Integer type
7
7
  #
8
8
  # @api private
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'utils'
3
+ require_relative '../../utils'
4
4
 
5
5
  module Shale
6
6
  module Schema
7
- class JSONCompiler
7
+ module Compiler
8
8
  # Class representing Shale's property
9
9
  #
10
10
  # @api private
11
11
  class Property
12
- # Return property's name
12
+ # Return mapping's name
13
13
  #
14
14
  # @return [String]
15
15
  #
16
16
  # @api private
17
- attr_reader :property_name
17
+ attr_reader :mapping_name
18
18
 
19
19
  # Return attribute's name
20
20
  #
@@ -33,13 +33,13 @@ module Shale
33
33
  # Initialize Property object
34
34
  #
35
35
  # @param [String] name
36
- # @param [Shale::Schema::JsonCompiler::Type] type
36
+ # @param [Shale::Schema::Compiler::Type] type
37
37
  # @param [true, false] collection
38
38
  # @param [Object] default
39
39
  #
40
40
  # @api private
41
41
  def initialize(name, type, collection, default)
42
- @property_name = name
42
+ @mapping_name = name
43
43
  @attribute_name = Utils.snake_case(name)
44
44
  @type = type
45
45
  @collection = collection
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale String type
7
7
  #
8
8
  # @api private
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shale
4
4
  module Schema
5
- class JSONCompiler
5
+ module Compiler
6
6
  # Class that maps Schema type to Shale Time type
7
7
  #
8
8
  # @api private
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shale
4
+ module Schema
5
+ module Compiler
6
+ # Class that maps Schema type to Shale Value type
7
+ #
8
+ # @api private
9
+ class Value
10
+ # Return name of the Shale type
11
+ #
12
+ # @return [String]
13
+ #
14
+ # @api private
15
+ def name
16
+ 'Shale::Type::Value'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'complex'
4
+
5
+ module Shale
6
+ module Schema
7
+ module Compiler
8
+ # Class representing Shale's XML complex type
9
+ #
10
+ # @api private
11
+ class XMLComplex < Complex
12
+ # Accessor for root attribute
13
+ #
14
+ # @return [String]
15
+ #
16
+ # @api private
17
+ attr_accessor :root
18
+
19
+ # Return namespace prefix
20
+ #
21
+ # @return [String]
22
+ #
23
+ # @api private
24
+ attr_reader :prefix
25
+
26
+ # Return namespace URI
27
+ #
28
+ # @return [String]
29
+ #
30
+ # @api private
31
+ attr_reader :namespace
32
+
33
+ # Initialize object
34
+ #
35
+ # @param [String] id
36
+ # @param [String] name
37
+ # @param [String] prefix
38
+ # @param [String] namespace
39
+ #
40
+ # @api private
41
+ def initialize(id, name, prefix, namespace)
42
+ super(id, name)
43
+ @root = name
44
+ @prefix = prefix
45
+ @namespace = namespace
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end