shale 0.9.0 → 1.1.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 +29 -0
- data/README.md +277 -50
- data/exe/shaleb +19 -4
- data/lib/shale/adapter/nokogiri.rb +1 -1
- data/lib/shale/adapter/ox.rb +2 -1
- data/lib/shale/error.rb +32 -8
- data/lib/shale/mapper.rb +7 -7
- data/lib/shale/mapping/delegates.rb +95 -0
- data/lib/shale/mapping/descriptor/dict.rb +19 -1
- data/lib/shale/mapping/descriptor/xml.rb +13 -2
- data/lib/shale/mapping/dict.rb +15 -4
- data/lib/shale/mapping/dict_base.rb +32 -4
- 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/base.rb +9 -3
- data/lib/shale/schema/json_generator/collection.rb +17 -2
- data/lib/shale/schema/json_generator/float.rb +6 -1
- data/lib/shale/schema/json_generator/integer.rb +6 -1
- data/lib/shale/schema/json_generator/object.rb +10 -2
- data/lib/shale/schema/json_generator/string.rb +5 -1
- data/lib/shale/schema/json_generator.rb +8 -4
- data/lib/shale/schema/xml_compiler.rb +58 -30
- data/lib/shale/schema/xml_generator.rb +3 -3
- data/lib/shale/schema.rb +10 -4
- data/lib/shale/type/complex.rb +176 -24
- data/lib/shale/utils.rb +22 -4
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +12 -16
- data/shale.gemspec +3 -1
- metadata +20 -5
@@ -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)
|
@@ -12,15 +12,21 @@ module Shale
|
|
12
12
|
# @api private
|
13
13
|
attr_reader :name
|
14
14
|
|
15
|
-
# Return
|
15
|
+
# Return schema hash
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
attr_reader :schema
|
19
|
+
|
20
|
+
# Set nullable
|
16
21
|
#
|
17
22
|
# @api private
|
18
23
|
attr_writer :nullable
|
19
24
|
|
20
|
-
def initialize(name, default: nil)
|
25
|
+
def initialize(name, default: nil, schema: nil)
|
21
26
|
@name = name.gsub('::', '_')
|
22
27
|
@default = default
|
23
|
-
@
|
28
|
+
@schema = schema || {}
|
29
|
+
@nullable = !schema&.[](:required)
|
24
30
|
end
|
25
31
|
|
26
32
|
# Return JSON Schema fragment as Ruby Hash
|
@@ -7,13 +7,20 @@ module Shale
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class Collection
|
10
|
+
# Return schema hash
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
attr_reader :schema
|
14
|
+
|
10
15
|
# Initialize Collection object
|
11
16
|
#
|
12
17
|
# @param [Shale::Schema::JSONGenerator::Base] type
|
18
|
+
# @param [Hash] schema
|
13
19
|
#
|
14
20
|
# @api private
|
15
|
-
def initialize(type)
|
21
|
+
def initialize(type, schema: nil)
|
16
22
|
@type = type
|
23
|
+
@schema = schema
|
17
24
|
end
|
18
25
|
|
19
26
|
# Delegate name to wrapped type object
|
@@ -31,7 +38,15 @@ module Shale
|
|
31
38
|
#
|
32
39
|
# @api private
|
33
40
|
def as_json
|
34
|
-
|
41
|
+
schema = @schema || {}
|
42
|
+
|
43
|
+
{ 'type' => 'array',
|
44
|
+
'items' => @type.as_type,
|
45
|
+
'minItems' => schema[:min_items],
|
46
|
+
'maxItems' => schema[:max_items],
|
47
|
+
'uniqueItems' => schema[:unique],
|
48
|
+
'minContains' => schema[:min_contains],
|
49
|
+
'maxContains' => schema[:max_contains] }.compact
|
35
50
|
end
|
36
51
|
end
|
37
52
|
end
|
@@ -15,7 +15,12 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'number'
|
18
|
+
{ 'type' => 'number',
|
19
|
+
'exclusiveMinimum' => schema[:exclusive_minimum],
|
20
|
+
'exclusiveMaximum' => schema[:exclusive_maximum],
|
21
|
+
'minimum' => schema[:minimum],
|
22
|
+
'maximum' => schema[:maximum],
|
23
|
+
'multipleOf' => schema[:multiple_of] }.compact
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -15,7 +15,12 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'integer'
|
18
|
+
{ 'type' => 'integer',
|
19
|
+
'exclusiveMinimum' => schema[:exclusive_minimum],
|
20
|
+
'exclusiveMaximum' => schema[:exclusive_maximum],
|
21
|
+
'minimum' => schema[:minimum],
|
22
|
+
'maximum' => schema[:maximum],
|
23
|
+
'multipleOf' => schema[:multiple_of] }.compact
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -16,10 +16,12 @@ module Shale
|
|
16
16
|
# Array<Shale::Schema::JSONGenerator::Base,
|
17
17
|
# Shale::Schema::JSONGenerator::Collection>
|
18
18
|
# ] properties
|
19
|
+
# @param [Hash] root
|
19
20
|
#
|
20
21
|
# @api private
|
21
|
-
def initialize(name, properties)
|
22
|
+
def initialize(name, properties, root)
|
22
23
|
super(name)
|
24
|
+
@root = root
|
23
25
|
@properties = properties
|
24
26
|
end
|
25
27
|
|
@@ -29,10 +31,16 @@ module Shale
|
|
29
31
|
#
|
30
32
|
# @api private
|
31
33
|
def as_type
|
34
|
+
required_props = @properties.filter_map { |prop| prop.name if prop&.schema&.[](:required) }
|
35
|
+
|
32
36
|
{
|
33
37
|
'type' => 'object',
|
34
38
|
'properties' => @properties.to_h { |el| [el.name, el.as_json] },
|
35
|
-
|
39
|
+
'required' => required_props.empty? ? nil : required_props,
|
40
|
+
'minProperties' => @root[:min_properties],
|
41
|
+
'maxProperties' => @root[:max_properties],
|
42
|
+
'dependentRequired' => @root[:dependent_required],
|
43
|
+
}.compact
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
@@ -15,7 +15,11 @@ module Shale
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def as_type
|
18
|
-
{ 'type' => 'string'
|
18
|
+
{ 'type' => 'string',
|
19
|
+
'format' => schema[:format],
|
20
|
+
'minLength' => schema[:min_length],
|
21
|
+
'maxLength' => schema[:max_length],
|
22
|
+
'pattern' => schema[:pattern] }.compact
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -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
|
|
@@ -96,14 +96,18 @@ module Shale
|
|
96
96
|
default = attribute.type.as_json(value)
|
97
97
|
end
|
98
98
|
|
99
|
-
json_type = json_klass.new(
|
99
|
+
json_type = json_klass.new(
|
100
|
+
mapping.name,
|
101
|
+
default: default,
|
102
|
+
schema: mapping.schema
|
103
|
+
)
|
100
104
|
end
|
101
105
|
|
102
|
-
json_type = Collection.new(json_type) if attribute.collection?
|
106
|
+
json_type = Collection.new(json_type, schema: mapping.schema) if attribute.collection?
|
103
107
|
properties << json_type
|
104
108
|
end
|
105
109
|
|
106
|
-
objects << Object.new(type.name, properties)
|
110
|
+
objects << Object.new(type.model.name, properties, type.json_mapping.root)
|
107
111
|
end
|
108
112
|
|
109
113
|
Schema.new(objects, id: id, title: title, description: description).as_json
|
@@ -34,51 +34,51 @@ module Shale
|
|
34
34
|
|
35
35
|
# XML Schema "schema" element name
|
36
36
|
# @api private
|
37
|
-
XS_SCHEMA = "#{XS_NAMESPACE_URI}:schema"
|
37
|
+
XS_SCHEMA = "#{XS_NAMESPACE_URI}:schema".freeze
|
38
38
|
|
39
39
|
# XML Schema "element" element name
|
40
40
|
# @api private
|
41
|
-
XS_ELEMENT = "#{XS_NAMESPACE_URI}:element"
|
41
|
+
XS_ELEMENT = "#{XS_NAMESPACE_URI}:element".freeze
|
42
42
|
|
43
43
|
# XML Schema "attribute" element name
|
44
44
|
# @api private
|
45
|
-
XS_ATTRIBUTE = "#{XS_NAMESPACE_URI}:attribute"
|
45
|
+
XS_ATTRIBUTE = "#{XS_NAMESPACE_URI}:attribute".freeze
|
46
46
|
|
47
47
|
# XML Schema "attribute" element name
|
48
48
|
# @api private
|
49
|
-
XS_SIMPLE_TYPE = "#{XS_NAMESPACE_URI}:simpleType"
|
49
|
+
XS_SIMPLE_TYPE = "#{XS_NAMESPACE_URI}:simpleType".freeze
|
50
50
|
|
51
51
|
# XML Schema "simpleContent" element name
|
52
52
|
# @api private
|
53
|
-
XS_SIMPLE_CONTENT = "#{XS_NAMESPACE_URI}:simpleContent"
|
53
|
+
XS_SIMPLE_CONTENT = "#{XS_NAMESPACE_URI}:simpleContent".freeze
|
54
54
|
|
55
55
|
# XML Schema "restriction" element name
|
56
56
|
# @api private
|
57
|
-
XS_RESTRICTION = "#{XS_NAMESPACE_URI}:restriction"
|
57
|
+
XS_RESTRICTION = "#{XS_NAMESPACE_URI}:restriction".freeze
|
58
58
|
|
59
59
|
# XML Schema "group" element name
|
60
60
|
# @api private
|
61
|
-
XS_GROUP = "#{XS_NAMESPACE_URI}:group"
|
61
|
+
XS_GROUP = "#{XS_NAMESPACE_URI}:group".freeze
|
62
62
|
|
63
63
|
# XML Schema "attributeGroup" element name
|
64
64
|
# @api private
|
65
|
-
XS_ATTRIBUTE_GROUP = "#{XS_NAMESPACE_URI}:attributeGroup"
|
65
|
+
XS_ATTRIBUTE_GROUP = "#{XS_NAMESPACE_URI}:attributeGroup".freeze
|
66
66
|
|
67
67
|
# XML Schema "complexType" element name
|
68
68
|
# @api private
|
69
|
-
XS_COMPLEX_TYPE = "#{XS_NAMESPACE_URI}:complexType"
|
69
|
+
XS_COMPLEX_TYPE = "#{XS_NAMESPACE_URI}:complexType".freeze
|
70
70
|
|
71
71
|
# XML Schema "complexContent" element name
|
72
72
|
# @api private
|
73
|
-
XS_COMPLEX_CONTENT = "#{XS_NAMESPACE_URI}:complexContent"
|
73
|
+
XS_COMPLEX_CONTENT = "#{XS_NAMESPACE_URI}:complexContent".freeze
|
74
74
|
|
75
75
|
# XML Schema "extension" element name
|
76
76
|
# @api private
|
77
|
-
XS_EXTENSION = "#{XS_NAMESPACE_URI}:extension"
|
77
|
+
XS_EXTENSION = "#{XS_NAMESPACE_URI}:extension".freeze
|
78
78
|
|
79
79
|
# XML Schema "anyType" type
|
80
80
|
# @api private
|
81
|
-
XS_TYPE_ANY = "#{XS_NAMESPACE_URI}:anyType"
|
81
|
+
XS_TYPE_ANY = "#{XS_NAMESPACE_URI}:anyType".freeze
|
82
82
|
|
83
83
|
# XML Schema "date" types
|
84
84
|
# @api private
|
@@ -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
|