shale 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|