shale 0.8.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +313 -62
- data/exe/shaleb +19 -4
- data/lib/shale/adapter/csv.rb +48 -0
- data/lib/shale/adapter/nokogiri/document.rb +7 -2
- data/lib/shale/adapter/nokogiri.rb +11 -4
- data/lib/shale/adapter/ox.rb +10 -4
- data/lib/shale/adapter/rexml.rb +18 -4
- data/lib/shale/error.rb +20 -8
- data/lib/shale/mapper.rb +41 -6
- data/lib/shale/mapping/delegates.rb +95 -0
- data/lib/shale/mapping/descriptor/dict.rb +10 -1
- data/lib/shale/mapping/descriptor/xml.rb +13 -2
- data/lib/shale/mapping/dict.rb +15 -5
- data/lib/shale/mapping/dict_base.rb +12 -6
- data/lib/shale/mapping/dict_group.rb +1 -1
- data/lib/shale/mapping/validator.rb +10 -3
- data/lib/shale/mapping/xml.rb +22 -6
- data/lib/shale/mapping/xml_base.rb +21 -12
- data/lib/shale/schema/compiler/complex.rb +52 -8
- data/lib/shale/schema/compiler/xml_complex.rb +5 -4
- data/lib/shale/schema/json_compiler.rb +27 -13
- data/lib/shale/schema/json_generator.rb +2 -2
- data/lib/shale/schema/xml_compiler.rb +46 -18
- data/lib/shale/schema/xml_generator.rb +3 -3
- data/lib/shale/schema.rb +10 -4
- data/lib/shale/type/complex.rb +291 -34
- data/lib/shale/type/date.rb +11 -0
- data/lib/shale/type/time.rb +11 -0
- data/lib/shale/type/value.rb +22 -0
- data/lib/shale/utils.rb +22 -4
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +30 -4
- data/shale.gemspec +2 -2
- metadata +7 -5
data/lib/shale/mapping/xml.rb
CHANGED
@@ -13,25 +13,28 @@ module Shale
|
|
13
13
|
#
|
14
14
|
# @param [String] element
|
15
15
|
# @param [Symbol, nil] to
|
16
|
+
# @param [Symbol, nil] receiver
|
16
17
|
# @param [Hash, nil] using
|
17
18
|
# @param [String, nil] namespace
|
18
19
|
# @param [String, nil] prefix
|
19
20
|
# @param [true, false] cdata
|
20
|
-
# @param [true, false] render_nil
|
21
|
+
# @param [true, false, nil] render_nil
|
21
22
|
#
|
22
23
|
# @api private
|
23
24
|
def map_element(
|
24
25
|
element,
|
25
26
|
to: nil,
|
27
|
+
receiver: nil,
|
26
28
|
using: nil,
|
27
29
|
namespace: :undefined,
|
28
30
|
prefix: :undefined,
|
29
31
|
cdata: false,
|
30
|
-
render_nil:
|
32
|
+
render_nil: nil
|
31
33
|
)
|
32
34
|
super(
|
33
35
|
element,
|
34
36
|
to: to,
|
37
|
+
receiver: receiver,
|
35
38
|
using: using,
|
36
39
|
namespace: namespace,
|
37
40
|
prefix: prefix,
|
@@ -44,23 +47,26 @@ module Shale
|
|
44
47
|
#
|
45
48
|
# @param [String] attribute
|
46
49
|
# @param [Symbol, nil] to
|
50
|
+
# @param [Symbol, nil] receiver
|
47
51
|
# @param [Hash, nil] using
|
48
52
|
# @param [String, nil] namespace
|
49
53
|
# @param [String, nil] prefix
|
50
|
-
# @param [true, false] render_nil
|
54
|
+
# @param [true, false, nil] render_nil
|
51
55
|
#
|
52
56
|
# @api private
|
53
57
|
def map_attribute(
|
54
58
|
attribute,
|
55
59
|
to: nil,
|
60
|
+
receiver: nil,
|
56
61
|
using: nil,
|
57
62
|
namespace: nil,
|
58
63
|
prefix: nil,
|
59
|
-
render_nil:
|
64
|
+
render_nil: nil
|
60
65
|
)
|
61
66
|
super(
|
62
67
|
attribute,
|
63
68
|
to: to,
|
69
|
+
receiver: receiver,
|
64
70
|
using: using,
|
65
71
|
namespace: namespace,
|
66
72
|
prefix: prefix,
|
@@ -71,12 +77,22 @@ module Shale
|
|
71
77
|
# Map document's content to object's attribute
|
72
78
|
#
|
73
79
|
# @param [Symbol] to
|
80
|
+
# @param [Symbol, nil] receiver
|
74
81
|
# @param [Hash, nil] using
|
75
82
|
# @param [true, false] cdata
|
76
83
|
#
|
77
84
|
# @api private
|
78
|
-
def map_content(to: nil, using: nil, cdata: false)
|
79
|
-
super(to: to, using: using, cdata: cdata)
|
85
|
+
def map_content(to: nil, receiver: nil, using: nil, cdata: false)
|
86
|
+
super(to: to, receiver: receiver, using: using, cdata: cdata)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Set render_nil default
|
90
|
+
#
|
91
|
+
# @param [true, false] val
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
def render_nil(val)
|
95
|
+
@render_nil_default = val
|
80
96
|
end
|
81
97
|
|
82
98
|
# Map group of nodes to mapping methods
|
@@ -67,18 +67,20 @@ module Shale
|
|
67
67
|
@root = ''
|
68
68
|
@default_namespace = Descriptor::XmlNamespace.new
|
69
69
|
@finalized = false
|
70
|
+
@render_nil_default = false
|
70
71
|
end
|
71
72
|
|
72
73
|
# Map element to attribute
|
73
74
|
#
|
74
75
|
# @param [String] element
|
75
76
|
# @param [Symbol, nil] to
|
77
|
+
# @param [Symbol, nil] receiver
|
76
78
|
# @param [Hash, nil] using
|
77
79
|
# @param [String, nil] group
|
78
80
|
# @param [String, nil] namespace
|
79
81
|
# @param [String, nil] prefix
|
80
82
|
# @param [true, false] cdata
|
81
|
-
# @param [true, false] render_nil
|
83
|
+
# @param [true, false, nil] render_nil
|
82
84
|
#
|
83
85
|
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
84
86
|
#
|
@@ -86,14 +88,15 @@ module Shale
|
|
86
88
|
def map_element(
|
87
89
|
element,
|
88
90
|
to: nil,
|
91
|
+
receiver: nil,
|
89
92
|
using: nil,
|
90
93
|
group: nil,
|
91
94
|
namespace: :undefined,
|
92
95
|
prefix: :undefined,
|
93
96
|
cdata: false,
|
94
|
-
render_nil:
|
97
|
+
render_nil: nil
|
95
98
|
)
|
96
|
-
Validator.validate_arguments(element, to, using)
|
99
|
+
Validator.validate_arguments(element, to, receiver, using)
|
97
100
|
Validator.validate_namespace(element, namespace, prefix)
|
98
101
|
|
99
102
|
if namespace == :undefined && prefix == :undefined
|
@@ -109,11 +112,12 @@ module Shale
|
|
109
112
|
@elements[namespaced_element] = Descriptor::Xml.new(
|
110
113
|
name: element,
|
111
114
|
attribute: to,
|
115
|
+
receiver: receiver,
|
112
116
|
methods: using,
|
113
117
|
group: group,
|
114
118
|
namespace: Descriptor::XmlNamespace.new(nsp, pfx),
|
115
119
|
cdata: cdata,
|
116
|
-
render_nil: render_nil
|
120
|
+
render_nil: render_nil.nil? ? @render_nil_default : render_nil
|
117
121
|
)
|
118
122
|
end
|
119
123
|
|
@@ -121,10 +125,12 @@ module Shale
|
|
121
125
|
#
|
122
126
|
# @param [String] attribute
|
123
127
|
# @param [Symbol, nil] to
|
128
|
+
# @param [Symbol, nil] receiver
|
124
129
|
# @param [Hash, nil] using
|
130
|
+
# @param [String, nil] group
|
125
131
|
# @param [String, nil] namespace
|
126
132
|
# @param [String, nil] prefix
|
127
|
-
# @param [true, false] render_nil
|
133
|
+
# @param [true, false, nil] render_nil
|
128
134
|
#
|
129
135
|
# @raise [IncorrectMappingArgumentsError] when arguments are incorrect
|
130
136
|
#
|
@@ -132,13 +138,14 @@ module Shale
|
|
132
138
|
def map_attribute(
|
133
139
|
attribute,
|
134
140
|
to: nil,
|
141
|
+
receiver: nil,
|
135
142
|
using: nil,
|
136
143
|
group: nil,
|
137
144
|
namespace: nil,
|
138
145
|
prefix: nil,
|
139
|
-
render_nil:
|
146
|
+
render_nil: nil
|
140
147
|
)
|
141
|
-
Validator.validate_arguments(attribute, to, using)
|
148
|
+
Validator.validate_arguments(attribute, to, receiver, using)
|
142
149
|
Validator.validate_namespace(attribute, namespace, prefix)
|
143
150
|
|
144
151
|
namespaced_attribute = [namespace, attribute].compact.join(':')
|
@@ -146,27 +153,31 @@ module Shale
|
|
146
153
|
@attributes[namespaced_attribute] = Descriptor::Xml.new(
|
147
154
|
name: attribute,
|
148
155
|
attribute: to,
|
156
|
+
receiver: receiver,
|
149
157
|
methods: using,
|
150
158
|
namespace: Descriptor::XmlNamespace.new(namespace, prefix),
|
151
159
|
cdata: false,
|
152
160
|
group: group,
|
153
|
-
render_nil: render_nil
|
161
|
+
render_nil: render_nil.nil? ? @render_nil_default : render_nil
|
154
162
|
)
|
155
163
|
end
|
156
164
|
|
157
165
|
# Map document's content to object's attribute
|
158
166
|
#
|
159
167
|
# @param [Symbol] to
|
168
|
+
# @param [Symbol, nil] receiver
|
160
169
|
# @param [Hash, nil] using
|
170
|
+
# @param [String, nil] group
|
161
171
|
# @param [true, false] cdata
|
162
172
|
#
|
163
173
|
# @api private
|
164
|
-
def map_content(to: nil, using: nil, group: nil, cdata: false)
|
165
|
-
Validator.validate_arguments('content', to, using)
|
174
|
+
def map_content(to: nil, receiver: nil, using: nil, group: nil, cdata: false)
|
175
|
+
Validator.validate_arguments('content', to, receiver, using)
|
166
176
|
|
167
177
|
@content = Descriptor::Xml.new(
|
168
178
|
name: nil,
|
169
179
|
attribute: to,
|
180
|
+
receiver: receiver,
|
170
181
|
methods: using,
|
171
182
|
namespace: Descriptor::XmlNamespace.new(nil, nil),
|
172
183
|
cdata: cdata,
|
@@ -215,8 +226,6 @@ module Shale
|
|
215
226
|
def initialize_dup(other)
|
216
227
|
@elements = other.instance_variable_get('@elements').dup
|
217
228
|
@attributes = other.instance_variable_get('@attributes').dup
|
218
|
-
@content = other.instance_variable_get('@content').dup
|
219
|
-
@root = other.instance_variable_get('@root').dup
|
220
229
|
@default_namespace = other.instance_variable_get('@default_namespace').dup
|
221
230
|
@finalized = false
|
222
231
|
|
@@ -23,32 +23,52 @@ module Shale
|
|
23
23
|
# @api private
|
24
24
|
attr_reader :properties
|
25
25
|
|
26
|
-
#
|
26
|
+
# Root name setter
|
27
27
|
#
|
28
28
|
# @param [String] val
|
29
29
|
#
|
30
30
|
# @api private
|
31
|
-
attr_writer :
|
31
|
+
attr_writer :root_name
|
32
32
|
|
33
33
|
# Initialize object
|
34
34
|
#
|
35
35
|
# @param [String] id
|
36
|
-
# @param [String]
|
36
|
+
# @param [String] root_name
|
37
|
+
# @param [String, nil] package
|
37
38
|
#
|
38
39
|
# @api private
|
39
|
-
def initialize(id,
|
40
|
+
def initialize(id, root_name, package)
|
40
41
|
@id = id
|
41
|
-
@
|
42
|
+
@root_name = root_name
|
43
|
+
@package = package ? Utils.classify(package) : nil
|
42
44
|
@properties = []
|
43
45
|
end
|
44
46
|
|
45
|
-
# Return name
|
47
|
+
# Return base name
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
def root_name
|
53
|
+
Utils.classify(@root_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return namespaced name
|
46
57
|
#
|
47
58
|
# @return [String]
|
48
59
|
#
|
49
60
|
# @api private
|
50
61
|
def name
|
51
|
-
Utils.classify(@
|
62
|
+
Utils.classify([@package, @root_name].compact.join('::'))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return module names
|
66
|
+
#
|
67
|
+
# @return [Array<String>]
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
def modules
|
71
|
+
(@package || '').split('::')
|
52
72
|
end
|
53
73
|
|
54
74
|
# Return file name
|
@@ -57,7 +77,31 @@ module Shale
|
|
57
77
|
#
|
58
78
|
# @api private
|
59
79
|
def file_name
|
60
|
-
Utils.snake_case(
|
80
|
+
Utils.snake_case(name)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return relative path to target
|
84
|
+
#
|
85
|
+
# @param [String] target
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
def relative_path(target)
|
91
|
+
base_paths = file_name.split('/')
|
92
|
+
target_paths = target.split('/')
|
93
|
+
|
94
|
+
common_paths_length = 0
|
95
|
+
|
96
|
+
base_paths.length.times do |i|
|
97
|
+
break if base_paths[i] != target_paths[i]
|
98
|
+
common_paths_length += 1
|
99
|
+
end
|
100
|
+
|
101
|
+
unique_base_paths = base_paths[common_paths_length..-1]
|
102
|
+
unique_target_paths = target_paths[common_paths_length..-1]
|
103
|
+
|
104
|
+
((0...unique_base_paths.length - 1).map { '..' } + unique_target_paths).join('/')
|
61
105
|
end
|
62
106
|
|
63
107
|
# Return references
|
@@ -33,14 +33,15 @@ module Shale
|
|
33
33
|
# Initialize object
|
34
34
|
#
|
35
35
|
# @param [String] id
|
36
|
-
# @param [String]
|
36
|
+
# @param [String] root_name
|
37
37
|
# @param [String] prefix
|
38
38
|
# @param [String] namespace
|
39
|
+
# @param [String, nil] package
|
39
40
|
#
|
40
41
|
# @api private
|
41
|
-
def initialize(id,
|
42
|
-
super(id,
|
43
|
-
@root =
|
42
|
+
def initialize(id, root_name, prefix, namespace, package)
|
43
|
+
super(id, root_name, package)
|
44
|
+
@root = root_name
|
44
45
|
@prefix = prefix
|
45
46
|
@namespace = namespace
|
46
47
|
end
|
@@ -4,6 +4,7 @@ require 'erb'
|
|
4
4
|
require 'uri'
|
5
5
|
|
6
6
|
require_relative '../../shale'
|
7
|
+
require_relative '../utils'
|
7
8
|
require_relative 'compiler/boolean'
|
8
9
|
require_relative 'compiler/complex'
|
9
10
|
require_relative 'compiler/date'
|
@@ -31,29 +32,37 @@ module Shale
|
|
31
32
|
<%- unless type.references.empty? -%>
|
32
33
|
|
33
34
|
<%- type.references.each do |property| -%>
|
34
|
-
require_relative '<%= property.type.file_name %>'
|
35
|
+
require_relative '<%= type.relative_path(property.type.file_name) %>'
|
35
36
|
<%- end -%>
|
36
37
|
<%- end -%>
|
37
38
|
|
38
|
-
|
39
|
+
<%- type.modules.each_with_index do |name, i| -%>
|
40
|
+
<%= ' ' * i %>module <%= name %>
|
41
|
+
<%- end -%>
|
42
|
+
<%- indent = ' ' * type.modules.length -%>
|
43
|
+
<%= indent %>class <%= type.root_name %> < Shale::Mapper
|
39
44
|
<%- type.properties.each do |property| -%>
|
40
|
-
attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
45
|
+
<%= indent %>attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
41
46
|
<%- if property.collection? %>, collection: true<% end -%>
|
42
47
|
<%- unless property.default.nil? %>, default: -> { <%= property.default %> }<% end %>
|
43
48
|
<%- end -%>
|
44
49
|
|
45
|
-
json do
|
50
|
+
<%= indent %>json do
|
46
51
|
<%- type.properties.each do |property| -%>
|
47
|
-
map '<%= property.mapping_name %>', to: :<%= property.attribute_name %>
|
52
|
+
<%= indent %>map '<%= property.mapping_name %>', to: :<%= property.attribute_name %>
|
48
53
|
<%- end -%>
|
49
|
-
end
|
50
|
-
end
|
54
|
+
<%= indent %>end
|
55
|
+
<%= indent %>end
|
56
|
+
<%- type.modules.length.times do |i| -%>
|
57
|
+
<%= ' ' * (type.modules.length - i - 1) %>end
|
58
|
+
<%- end -%>
|
51
59
|
TEMPLATE
|
52
60
|
|
53
61
|
# Generate Shale models from JSON Schema and return them as a Ruby Array of objects
|
54
62
|
#
|
55
63
|
# @param [Array<String>] schemas
|
56
64
|
# @param [String, nil] root_name
|
65
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
57
66
|
#
|
58
67
|
# @raise [SchemaError] when JSON Schema has errors
|
59
68
|
#
|
@@ -63,12 +72,13 @@ module Shale
|
|
63
72
|
# Shale::Schema::JSONCompiler.new.as_models([schema1, schema2])
|
64
73
|
#
|
65
74
|
# @api public
|
66
|
-
def as_models(schemas, root_name: nil)
|
75
|
+
def as_models(schemas, root_name: nil, namespace_mapping: nil)
|
67
76
|
schemas = schemas.map do |schema|
|
68
77
|
Shale.json_adapter.load(schema)
|
69
78
|
end
|
70
79
|
|
71
80
|
@root_name = root_name
|
81
|
+
@namespace_mapping = namespace_mapping || {}
|
72
82
|
@schema_repository = {}
|
73
83
|
@types = []
|
74
84
|
|
@@ -89,7 +99,7 @@ module Shale
|
|
89
99
|
duplicates[type.name] += 1
|
90
100
|
|
91
101
|
if total_duplicates[type.name] > 1
|
92
|
-
type.
|
102
|
+
type.root_name = format("#{type.root_name}%d", duplicates[type.name])
|
93
103
|
end
|
94
104
|
end
|
95
105
|
|
@@ -100,6 +110,7 @@ module Shale
|
|
100
110
|
#
|
101
111
|
# @param [Array<String>] schemas
|
102
112
|
# @param [String, nil] root_name
|
113
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
103
114
|
#
|
104
115
|
# @raise [SchemaError] when JSON Schema has errors
|
105
116
|
#
|
@@ -109,8 +120,8 @@ module Shale
|
|
109
120
|
# Shale::Schema::JSONCompiler.new.to_models([schema1, schema2])
|
110
121
|
#
|
111
122
|
# @api public
|
112
|
-
def to_models(schemas, root_name: nil)
|
113
|
-
types = as_models(schemas, root_name: root_name)
|
123
|
+
def to_models(schemas, root_name: nil, namespace_mapping: nil)
|
124
|
+
types = as_models(schemas, root_name: root_name, namespace_mapping: namespace_mapping)
|
114
125
|
|
115
126
|
types.to_h do |type|
|
116
127
|
[type.file_name, MODEL_TEMPLATE.result(binding)]
|
@@ -207,7 +218,8 @@ module Shale
|
|
207
218
|
end
|
208
219
|
|
209
220
|
if type == 'object'
|
210
|
-
|
221
|
+
base_id = Utils.presence(id.split('#')[0])
|
222
|
+
Compiler::Complex.new(id, name, @namespace_mapping[base_id])
|
211
223
|
elsif type == 'string' && format == 'date'
|
212
224
|
Compiler::Date.new
|
213
225
|
elsif type == 'string' && format == 'date-time'
|
@@ -297,7 +309,9 @@ module Shale
|
|
297
309
|
if schema.is_a?(Hash) && schema.key?('$ref')
|
298
310
|
entry = resolve_ref(id, schema['$ref'])
|
299
311
|
schema = entry[:schema]
|
300
|
-
|
312
|
+
entry_id, entry_fragment = entry[:id].split('#')
|
313
|
+
id = build_id(id, entry_id)
|
314
|
+
fragment = (entry_fragment || '').split('/') - ['']
|
301
315
|
end
|
302
316
|
|
303
317
|
pointer = entry[:id] || build_pointer(id, fragment)
|
@@ -87,7 +87,7 @@ module Shale
|
|
87
87
|
next unless attribute
|
88
88
|
|
89
89
|
if mapper_type?(attribute.type)
|
90
|
-
json_type = Ref.new(mapping.name, attribute.type.name)
|
90
|
+
json_type = Ref.new(mapping.name, attribute.type.model.name)
|
91
91
|
else
|
92
92
|
json_klass = self.class.get_json_type(attribute.type)
|
93
93
|
|
@@ -103,7 +103,7 @@ module Shale
|
|
103
103
|
properties << json_type
|
104
104
|
end
|
105
105
|
|
106
|
-
objects << Object.new(type.name, properties)
|
106
|
+
objects << Object.new(type.model.name, properties)
|
107
107
|
end
|
108
108
|
|
109
109
|
Schema.new(objects, id: id, title: title, description: description).as_json
|
@@ -139,55 +139,63 @@ module Shale
|
|
139
139
|
<%- unless type.references.empty? -%>
|
140
140
|
|
141
141
|
<%- type.references.each do |property| -%>
|
142
|
-
require_relative '<%= property.type.file_name %>'
|
142
|
+
require_relative '<%= type.relative_path(property.type.file_name) %>'
|
143
143
|
<%- end -%>
|
144
144
|
<%- end -%>
|
145
145
|
|
146
|
-
|
146
|
+
<%- type.modules.each_with_index do |name, i| -%>
|
147
|
+
<%= ' ' * i %>module <%= name %>
|
148
|
+
<%- end -%>
|
149
|
+
<%- indent = ' ' * type.modules.length -%>
|
150
|
+
<%= indent %>class <%= type.root_name %> < Shale::Mapper
|
147
151
|
<%- type.properties.select(&:content?).each do |property| -%>
|
148
|
-
attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
152
|
+
<%= indent %>attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
149
153
|
<%- if property.collection? %>, collection: true<% end -%>
|
150
154
|
<%- unless property.default.nil? %>, default: -> { <%= property.default %> }<% end %>
|
151
155
|
<%- end -%>
|
152
156
|
<%- type.properties.select(&:attribute?).each do |property| -%>
|
153
|
-
attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
157
|
+
<%= indent %>attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
154
158
|
<%- if property.collection? %>, collection: true<% end -%>
|
155
159
|
<%- unless property.default.nil? %>, default: -> { <%= property.default %> }<% end %>
|
156
160
|
<%- end -%>
|
157
161
|
<%- type.properties.select(&:element?).each do |property| -%>
|
158
|
-
attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
162
|
+
<%= indent %>attribute :<%= property.attribute_name %>, <%= property.type.name -%>
|
159
163
|
<%- if property.collection? %>, collection: true<% end -%>
|
160
164
|
<%- unless property.default.nil? %>, default: -> { <%= property.default %> }<% end %>
|
161
165
|
<%- end -%>
|
162
166
|
|
163
|
-
xml do
|
164
|
-
root '<%= type.root %>'
|
167
|
+
<%= indent %>xml do
|
168
|
+
<%= indent %>root '<%= type.root %>'
|
165
169
|
<%- if type.namespace -%>
|
166
|
-
namespace '<%= type.namespace %>', '<%= type.prefix %>'
|
170
|
+
<%= indent %>namespace '<%= type.namespace %>', '<%= type.prefix %>'
|
167
171
|
<%- end -%>
|
168
172
|
<%- unless type.properties.empty? -%>
|
169
173
|
|
170
174
|
<%- type.properties.select(&:content?).each do |property| -%>
|
171
|
-
map_content to: :<%= property.attribute_name %>
|
175
|
+
<%= indent %>map_content to: :<%= property.attribute_name %>
|
172
176
|
<%- end -%>
|
173
177
|
<%- type.properties.select(&:attribute?).each do |property| -%>
|
174
|
-
map_attribute '<%= property.mapping_name %>', to: :<%= property.attribute_name -%>
|
178
|
+
<%= indent %>map_attribute '<%= property.mapping_name %>', to: :<%= property.attribute_name -%>
|
175
179
|
<%- if property.namespace %>, prefix: '<%= property.prefix %>'<%- end -%>
|
176
180
|
<%- if property.namespace %>, namespace: '<%= property.namespace %>'<% end %>
|
177
181
|
<%- end -%>
|
178
182
|
<%- type.properties.select(&:element?).each do |property| -%>
|
179
|
-
map_element '<%= property.mapping_name %>', to: :<%= property.attribute_name -%>
|
183
|
+
<%= indent %>map_element '<%= property.mapping_name %>', to: :<%= property.attribute_name -%>
|
180
184
|
<%- if type.namespace != property.namespace %>, prefix: <%= property.prefix ? "'\#{property.prefix}'" : 'nil' %><%- end -%>
|
181
185
|
<%- if type.namespace != property.namespace %>, namespace: <%= property.namespace ? "'\#{property.namespace}'" : 'nil' %><% end %>
|
182
186
|
<%- end -%>
|
183
187
|
<%- end -%>
|
184
|
-
end
|
185
|
-
end
|
188
|
+
<%= indent %>end
|
189
|
+
<%= indent %>end
|
190
|
+
<%- type.modules.length.times do |i| -%>
|
191
|
+
<%= ' ' * (type.modules.length - i - 1) %>end
|
192
|
+
<%- end -%>
|
186
193
|
TEMPLATE
|
187
194
|
|
188
195
|
# Generate Shale models from XML Schema and return them as a Ruby Array of objects
|
189
196
|
#
|
190
197
|
# @param [Array<String>] schemas
|
198
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
191
199
|
#
|
192
200
|
# @raise [AdapterError] when XML adapter is not set or Ox adapter is used
|
193
201
|
# @raise [SchemaError] when XML Schema has errors
|
@@ -198,7 +206,7 @@ module Shale
|
|
198
206
|
# Shale::Schema::XMLCompiler.new.as_models([schema1, schema2])
|
199
207
|
#
|
200
208
|
# @api public
|
201
|
-
def as_models(schemas)
|
209
|
+
def as_models(schemas, namespace_mapping: nil)
|
202
210
|
unless Shale.xml_adapter
|
203
211
|
raise AdapterError, XML_ADAPTER_NOT_SET_MESSAGE
|
204
212
|
end
|
@@ -212,6 +220,7 @@ module Shale
|
|
212
220
|
Shale.xml_adapter.load(schema)
|
213
221
|
end
|
214
222
|
|
223
|
+
@namespace_mapping = namespace_mapping || {}
|
215
224
|
@elements_repository = {}
|
216
225
|
@attributes_repository = {}
|
217
226
|
@simple_types_repository = {}
|
@@ -244,7 +253,7 @@ module Shale
|
|
244
253
|
duplicates[type.name] += 1
|
245
254
|
|
246
255
|
if total_duplicates[type.name] > 1
|
247
|
-
type.
|
256
|
+
type.root_name = format("#{type.root_name}%d", duplicates[type.name])
|
248
257
|
end
|
249
258
|
end
|
250
259
|
|
@@ -256,6 +265,7 @@ module Shale
|
|
256
265
|
# Generate Shale models from XML Schema
|
257
266
|
#
|
258
267
|
# @param [Array<String>] schemas
|
268
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
259
269
|
#
|
260
270
|
# @raise [SchemaError] when XML Schema has errors
|
261
271
|
#
|
@@ -265,8 +275,8 @@ module Shale
|
|
265
275
|
# Shale::Schema::XMLCompiler.new.to_models([schema1, schema2])
|
266
276
|
#
|
267
277
|
# @api public
|
268
|
-
def to_models(schemas)
|
269
|
-
types = as_models(schemas)
|
278
|
+
def to_models(schemas, namespace_mapping: nil)
|
279
|
+
types = as_models(schemas, namespace_mapping: namespace_mapping)
|
270
280
|
|
271
281
|
types.to_h do |type|
|
272
282
|
[type.file_name, MODEL_TEMPLATE.result(binding)]
|
@@ -415,6 +425,10 @@ module Shale
|
|
415
425
|
type = type.sub(/^#{prefix}/, name)
|
416
426
|
end
|
417
427
|
|
428
|
+
if namespaces.key?('xmlns') && !type.include?(':')
|
429
|
+
type = "#{namespaces['xmlns']}:#{type}"
|
430
|
+
end
|
431
|
+
|
418
432
|
type
|
419
433
|
end
|
420
434
|
|
@@ -535,7 +549,13 @@ module Shale
|
|
535
549
|
name = node.attributes['name'] || node.parent.attributes['name']
|
536
550
|
prefix, namespace = resolve_complex_type_namespace(node)
|
537
551
|
|
538
|
-
@complex_types[id] = Compiler::XMLComplex.new(
|
552
|
+
@complex_types[id] = Compiler::XMLComplex.new(
|
553
|
+
id,
|
554
|
+
name,
|
555
|
+
prefix,
|
556
|
+
namespace,
|
557
|
+
@namespace_mapping[namespace]
|
558
|
+
)
|
539
559
|
end
|
540
560
|
end
|
541
561
|
end
|
@@ -571,6 +591,14 @@ module Shale
|
|
571
591
|
infer_type_from_xs_type(type, namespaces)
|
572
592
|
end
|
573
593
|
|
594
|
+
# Infer type from XSD type
|
595
|
+
#
|
596
|
+
# @param [String] type
|
597
|
+
# @param [Hash<String, String>] namespaces
|
598
|
+
#
|
599
|
+
# @return [Shale::Schema::Compiler::<any>]
|
600
|
+
#
|
601
|
+
# @api private
|
574
602
|
def infer_type_from_xs_type(type, namespaces)
|
575
603
|
type = replace_ns_prefixes(type, namespaces)
|
576
604
|
|
@@ -84,7 +84,7 @@ module Shale
|
|
84
84
|
|
85
85
|
root_element = TypedElement.new(
|
86
86
|
name: klass.xml_mapping.unprefixed_root,
|
87
|
-
type: [default_namespace.prefix, schematize(klass.name)].compact.join(':'),
|
87
|
+
type: [default_namespace.prefix, schematize(klass.model.name)].compact.join(':'),
|
88
88
|
required: true
|
89
89
|
)
|
90
90
|
|
@@ -195,7 +195,7 @@ module Shale
|
|
195
195
|
end
|
196
196
|
|
197
197
|
complex = ComplexType.new(
|
198
|
-
schematize(type.name),
|
198
|
+
schematize(type.model.name),
|
199
199
|
children,
|
200
200
|
mixed: !type.xml_mapping.content.nil?
|
201
201
|
)
|
@@ -287,7 +287,7 @@ module Shale
|
|
287
287
|
# @api private
|
288
288
|
def get_xml_type_for_attribute(type, namespace)
|
289
289
|
if mapper_type?(type)
|
290
|
-
[namespace.prefix, schematize(type.name)].compact.join(':')
|
290
|
+
[namespace.prefix, schematize(type.model.name)].compact.join(':')
|
291
291
|
else
|
292
292
|
"xs:#{self.class.get_xml_type(type)}"
|
293
293
|
end
|
data/lib/shale/schema.rb
CHANGED
@@ -38,6 +38,7 @@ module Shale
|
|
38
38
|
#
|
39
39
|
# @param [Array<String>] schemas
|
40
40
|
# @param [String, nil] root_name
|
41
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
41
42
|
#
|
42
43
|
# @return [Array<String>]
|
43
44
|
#
|
@@ -46,8 +47,12 @@ module Shale
|
|
46
47
|
# # => [model1, model2, model3]
|
47
48
|
#
|
48
49
|
# @api public
|
49
|
-
def self.from_json(schemas, root_name: nil)
|
50
|
-
JSONCompiler.new.to_models(
|
50
|
+
def self.from_json(schemas, root_name: nil, namespace_mapping: nil)
|
51
|
+
JSONCompiler.new.to_models(
|
52
|
+
schemas,
|
53
|
+
root_name: root_name,
|
54
|
+
namespace_mapping: namespace_mapping
|
55
|
+
)
|
51
56
|
end
|
52
57
|
|
53
58
|
# Generate XML Schema from Shale model
|
@@ -71,6 +76,7 @@ module Shale
|
|
71
76
|
# Generate Shale model from XML Schema
|
72
77
|
#
|
73
78
|
# @param [Array<String>] schemas
|
79
|
+
# @param [Hash<String, String>, nil] namespace_mapping
|
74
80
|
#
|
75
81
|
# @return [Array<String>]
|
76
82
|
#
|
@@ -79,8 +85,8 @@ module Shale
|
|
79
85
|
# # => [model1, model2, model3]
|
80
86
|
#
|
81
87
|
# @api public
|
82
|
-
def self.from_xml(schemas)
|
83
|
-
XMLCompiler.new.to_models(schemas)
|
88
|
+
def self.from_xml(schemas, namespace_mapping: nil)
|
89
|
+
XMLCompiler.new.to_models(schemas, namespace_mapping: namespace_mapping)
|
84
90
|
end
|
85
91
|
end
|
86
92
|
end
|