shale 0.2.2 → 0.3.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 +13 -0
- data/README.md +270 -5
- data/exe/shaleb +75 -0
- data/lib/shale/adapter/json.rb +7 -2
- data/lib/shale/adapter/nokogiri.rb +48 -12
- data/lib/shale/adapter/ox.rb +28 -4
- data/lib/shale/adapter/rexml.rb +56 -13
- data/lib/shale/attribute.rb +1 -1
- data/lib/shale/error.rb +6 -0
- data/lib/shale/mapper.rb +11 -11
- data/lib/shale/mapping/descriptor/dict.rb +57 -0
- data/lib/shale/mapping/descriptor/xml.rb +43 -0
- data/lib/shale/mapping/descriptor/xml_namespace.rb +37 -0
- data/lib/shale/mapping/{key_value.rb → dict.rb} +8 -6
- data/lib/shale/mapping/validator.rb +51 -0
- data/lib/shale/mapping/xml.rb +86 -15
- data/lib/shale/schema/json/base.rb +41 -0
- data/lib/shale/schema/json/boolean.rb +23 -0
- data/lib/shale/schema/json/collection.rb +39 -0
- data/lib/shale/schema/json/date.rb +23 -0
- data/lib/shale/schema/json/float.rb +23 -0
- data/lib/shale/schema/json/integer.rb +23 -0
- data/lib/shale/schema/json/object.rb +37 -0
- data/lib/shale/schema/json/ref.rb +28 -0
- data/lib/shale/schema/json/schema.rb +57 -0
- data/lib/shale/schema/json/string.rb +23 -0
- data/lib/shale/schema/json/time.rb +23 -0
- data/lib/shale/schema/json.rb +165 -0
- data/lib/shale/schema/xml/attribute.rb +41 -0
- data/lib/shale/schema/xml/complex_type.rb +67 -0
- data/lib/shale/schema/xml/element.rb +55 -0
- data/lib/shale/schema/xml/import.rb +46 -0
- data/lib/shale/schema/xml/ref_attribute.rb +37 -0
- data/lib/shale/schema/xml/ref_element.rb +39 -0
- data/lib/shale/schema/xml/schema.rb +121 -0
- data/lib/shale/schema/xml/typed_attribute.rb +46 -0
- data/lib/shale/schema/xml/typed_element.rb +46 -0
- data/lib/shale/schema/xml.rb +316 -0
- data/lib/shale/schema.rb +47 -0
- data/lib/shale/type/boolean.rb +2 -2
- data/lib/shale/type/composite.rb +66 -54
- data/lib/shale/type/date.rb +35 -2
- data/lib/shale/type/float.rb +2 -2
- data/lib/shale/type/integer.rb +2 -2
- data/lib/shale/type/string.rb +2 -2
- data/lib/shale/type/time.rb +35 -2
- data/lib/shale/type/{base.rb → value.rb} +18 -7
- data/lib/shale/utils.rb +18 -2
- data/lib/shale/version.rb +1 -1
- data/lib/shale.rb +10 -10
- data/shale.gemspec +6 -2
- metadata +41 -13
- data/lib/shale/mapping/base.rb +0 -32
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shale
|
4
|
+
module Schema
|
5
|
+
class JSON
|
6
|
+
# Class representing array type in JSON Schema
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Collection
|
10
|
+
# Initialize Collection object
|
11
|
+
#
|
12
|
+
# @param [Shale::Schema::JSON::Base] type
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def initialize(type)
|
16
|
+
@type = type
|
17
|
+
end
|
18
|
+
|
19
|
+
# Delegate name to wrapped type object
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
def name
|
25
|
+
@type.name
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return JSON Schema fragment as Ruby Hash
|
29
|
+
#
|
30
|
+
# @return [Hash]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def as_json
|
34
|
+
{ 'type' => 'array', 'items' => @type.as_type }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema date type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Date < Base
|
12
|
+
# Return JSON Schema fragment as Ruby Hash
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def as_type
|
18
|
+
{ 'type' => 'string', 'format' => 'date' }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema float type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Float < Base
|
12
|
+
# Return JSON Schema fragment as Ruby Hash
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def as_type
|
18
|
+
{ 'type' => 'number' }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema integer type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Integer < Base
|
12
|
+
# Return JSON Schema fragment as Ruby Hash
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def as_type
|
18
|
+
{ 'type' => 'integer' }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema object type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Object < Base
|
12
|
+
# Initialize object
|
13
|
+
#
|
14
|
+
# @param [String] name
|
15
|
+
# @param [Array<Shale::Schema::JSON::Base, Shale::Schema::JSON::Collection>] properties
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
def initialize(name, properties)
|
19
|
+
super(name)
|
20
|
+
@properties = properties
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return JSON Schema fragment as Ruby Hash
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
def as_type
|
29
|
+
{
|
30
|
+
'type' => 'object',
|
31
|
+
'properties' => @properties.to_h { |el| [el.name, el.as_json] },
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema reference
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Ref < Base
|
12
|
+
def initialize(name, type)
|
13
|
+
super(name)
|
14
|
+
@type = type.gsub('::', '_')
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return JSON Schema fragment as Ruby Hash
|
18
|
+
#
|
19
|
+
# @return [Hash]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
def as_type
|
23
|
+
{ '$ref' => "#/$defs/#{@type}" }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shale
|
4
|
+
module Schema
|
5
|
+
class JSON
|
6
|
+
# Class representing JSON schema
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Schema
|
10
|
+
# JSON Schema dialect (aka version)
|
11
|
+
# @api private
|
12
|
+
DIALECT = 'https://json-schema.org/draft/2020-12/schema'
|
13
|
+
|
14
|
+
# Initialize Schema object
|
15
|
+
#
|
16
|
+
# @param [Array<Shale::Schema::JSON::Base>] types
|
17
|
+
# @param [String, nil] id
|
18
|
+
# @param [String, nil] description
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
def initialize(types, id: nil, description: nil)
|
22
|
+
@types = types
|
23
|
+
@id = id
|
24
|
+
@description = description
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return JSON schema as Ruby Hash
|
28
|
+
#
|
29
|
+
# @return [Hash]
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Shale::Schema::JSON::Schema.new(types).as_json
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
def as_json
|
36
|
+
schema = {
|
37
|
+
'$schema' => DIALECT,
|
38
|
+
'id' => @id,
|
39
|
+
'description' => @description,
|
40
|
+
}
|
41
|
+
|
42
|
+
unless @types.empty?
|
43
|
+
root = @types.first
|
44
|
+
root.nullable = false
|
45
|
+
|
46
|
+
schema['$ref'] = "#/$defs/#{root.name}"
|
47
|
+
schema['$defs'] = @types
|
48
|
+
.sort { |a, b| a.name <=> b.name }
|
49
|
+
.to_h { |e| [e.name, e.as_json] }
|
50
|
+
end
|
51
|
+
|
52
|
+
schema.compact
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema string type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class String < Base
|
12
|
+
# Return JSON Schema fragment as Ruby Hash
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def as_type
|
18
|
+
{ 'type' => 'string' }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class JSON
|
8
|
+
# Class representing JSON Schema time type
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Time < Base
|
12
|
+
# Return JSON Schema fragment as Ruby Hash
|
13
|
+
#
|
14
|
+
# @return [Hash]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def as_type
|
18
|
+
{ 'type' => 'string', 'format' => 'date-time' }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../shale'
|
4
|
+
require_relative 'json/schema'
|
5
|
+
require_relative 'json/boolean'
|
6
|
+
require_relative 'json/collection'
|
7
|
+
require_relative 'json/date'
|
8
|
+
require_relative 'json/float'
|
9
|
+
require_relative 'json/integer'
|
10
|
+
require_relative 'json/object'
|
11
|
+
require_relative 'json/ref'
|
12
|
+
require_relative 'json/string'
|
13
|
+
require_relative 'json/time'
|
14
|
+
|
15
|
+
module Shale
|
16
|
+
module Schema
|
17
|
+
# Class for handling JSON schema
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
class JSON
|
21
|
+
@json_types = Hash.new(Shale::Schema::JSON::String)
|
22
|
+
|
23
|
+
# Register Shale to JSON type mapping
|
24
|
+
#
|
25
|
+
# @param [Shale::Type::Value] shale_type
|
26
|
+
# @param [Shale::Schema::JSON::Base] json_type
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# Shale::Schema::JSON.register_json_type(Shale::Type::String, MyCustomJsonType)
|
30
|
+
#
|
31
|
+
# @api public
|
32
|
+
def self.register_json_type(shale_type, json_type)
|
33
|
+
@json_types[shale_type] = json_type
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return JSON type for given Shale type
|
37
|
+
#
|
38
|
+
# @param [Shale::Type::Value] shale_type
|
39
|
+
#
|
40
|
+
# @return [Shale::Schema::JSON::Base]
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Shale::Schema::JSON.get_json_type(Shale::Type::String)
|
44
|
+
# # => Shale::Schema::JSON::String
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
def self.get_json_type(shale_type)
|
48
|
+
@json_types[shale_type]
|
49
|
+
end
|
50
|
+
|
51
|
+
register_json_type(Shale::Type::Boolean, Shale::Schema::JSON::Boolean)
|
52
|
+
register_json_type(Shale::Type::Date, Shale::Schema::JSON::Date)
|
53
|
+
register_json_type(Shale::Type::Float, Shale::Schema::JSON::Float)
|
54
|
+
register_json_type(Shale::Type::Integer, Shale::Schema::JSON::Integer)
|
55
|
+
register_json_type(Shale::Type::Time, Shale::Schema::JSON::Time)
|
56
|
+
|
57
|
+
# Generate JSON Schema from Shale model and return it as a Ruby Hash
|
58
|
+
#
|
59
|
+
# @param [Shale::Mapper] klass
|
60
|
+
# @param [String, nil] id
|
61
|
+
# @param [String, nil] description
|
62
|
+
#
|
63
|
+
# @raise [NotAShaleMapperError] when attribute is not a Shale model
|
64
|
+
#
|
65
|
+
# @return [Hash]
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# Shale::Schema::JSON.new.as_schema(Person)
|
69
|
+
#
|
70
|
+
# @api public
|
71
|
+
def as_schema(klass, id: nil, description: nil)
|
72
|
+
unless mapper_type?(klass)
|
73
|
+
raise NotAShaleMapperError, "JSON Shema can't be generated for '#{klass}' type"
|
74
|
+
end
|
75
|
+
|
76
|
+
types = collect_composite_types(klass)
|
77
|
+
objects = []
|
78
|
+
|
79
|
+
types.each do |type|
|
80
|
+
properties = []
|
81
|
+
|
82
|
+
type.json_mapping.keys.values.each do |mapping|
|
83
|
+
attribute = type.attributes[mapping.attribute]
|
84
|
+
next unless attribute
|
85
|
+
|
86
|
+
if mapper_type?(attribute.type)
|
87
|
+
json_type = Ref.new(mapping.name, attribute.type.name)
|
88
|
+
else
|
89
|
+
json_klass = self.class.get_json_type(attribute.type)
|
90
|
+
|
91
|
+
if attribute.default && !attribute.collection?
|
92
|
+
value = attribute.type.cast(attribute.default.call)
|
93
|
+
default = attribute.type.as_json(value)
|
94
|
+
end
|
95
|
+
|
96
|
+
json_type = json_klass.new(mapping.name, default: default)
|
97
|
+
end
|
98
|
+
|
99
|
+
json_type = Collection.new(json_type) if attribute.collection?
|
100
|
+
properties << json_type
|
101
|
+
end
|
102
|
+
|
103
|
+
objects << Object.new(type.name, properties)
|
104
|
+
end
|
105
|
+
|
106
|
+
Schema.new(objects, id: id, description: description).as_json
|
107
|
+
end
|
108
|
+
|
109
|
+
# Generate JSON Schema from Shale model
|
110
|
+
#
|
111
|
+
# @param [Shale::Mapper] klass
|
112
|
+
# @param [String, nil] id
|
113
|
+
# @param [String, nil] description
|
114
|
+
# @param [true, false] pretty
|
115
|
+
#
|
116
|
+
# @return [String]
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# Shale::Schema::JSON.new.to_schema(Person)
|
120
|
+
#
|
121
|
+
# @api public
|
122
|
+
def to_schema(klass, id: nil, description: nil, pretty: false)
|
123
|
+
schema = as_schema(klass, id: id, description: description)
|
124
|
+
options = pretty ? :pretty : nil
|
125
|
+
|
126
|
+
Shale.json_adapter.dump(schema, options)
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# Check it type inherits from Shale::Mapper
|
132
|
+
#
|
133
|
+
# @param [Class] type
|
134
|
+
#
|
135
|
+
# @return [true, false]
|
136
|
+
#
|
137
|
+
# @api private
|
138
|
+
def mapper_type?(type)
|
139
|
+
type < Shale::Mapper
|
140
|
+
end
|
141
|
+
|
142
|
+
# Collect recursively Shale::Mapper types
|
143
|
+
#
|
144
|
+
# @param [Shale::Mapper] type
|
145
|
+
#
|
146
|
+
# @return [Array<Shale::Mapper>]
|
147
|
+
#
|
148
|
+
# @api private
|
149
|
+
def collect_composite_types(type)
|
150
|
+
types = [type]
|
151
|
+
|
152
|
+
type.json_mapping.keys.values.each do |mapping|
|
153
|
+
attribute = type.attributes[mapping.attribute]
|
154
|
+
next unless attribute
|
155
|
+
|
156
|
+
if mapper_type?(attribute.type) && !types.include?(attribute.type)
|
157
|
+
types += collect_composite_types(attribute.type)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
types.uniq
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shale
|
4
|
+
module Schema
|
5
|
+
class XML
|
6
|
+
# Class representing XML Schema <attribute> element.
|
7
|
+
# Serves as a base class for TypedAttribute and RefAttribute
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class Attribute
|
11
|
+
# Initialize Attribute object
|
12
|
+
#
|
13
|
+
# @param [String, nil] default
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def initialize(default)
|
17
|
+
@default = default
|
18
|
+
end
|
19
|
+
|
20
|
+
# Append element to the XML document
|
21
|
+
#
|
22
|
+
# @param [Shale::Adapter::<XML adapter>::Document] doc
|
23
|
+
#
|
24
|
+
# @return [Shale::Adapter::<XML adapter>::Node]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def as_xml(doc)
|
28
|
+
attribute = doc.create_element('xs:attribute')
|
29
|
+
|
30
|
+
attributes.each do |name, value|
|
31
|
+
doc.add_attribute(attribute, name, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
doc.add_attribute(attribute, 'default', @default) unless @default.nil?
|
35
|
+
|
36
|
+
attribute
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'attribute'
|
4
|
+
require_relative 'element'
|
5
|
+
|
6
|
+
module Shale
|
7
|
+
module Schema
|
8
|
+
class XML
|
9
|
+
# Class representing XML Schema <complexType> element
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class ComplexType
|
13
|
+
# Return name
|
14
|
+
#
|
15
|
+
# @return [String]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
attr_reader :name
|
19
|
+
|
20
|
+
# Initialize ComplexType object
|
21
|
+
#
|
22
|
+
# @param [String] name
|
23
|
+
# @param [Array<Shale::Schema::XML::Element, Shale::Schema::XML::Attribute>] children
|
24
|
+
# @param [true, false] mixed
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
def initialize(name, children = [], mixed: false)
|
28
|
+
@name = name
|
29
|
+
@children = children
|
30
|
+
@mixed = mixed
|
31
|
+
end
|
32
|
+
|
33
|
+
# Append element to the XML document
|
34
|
+
#
|
35
|
+
# @param [Shale::Adapter::<XML adapter>::Document] doc
|
36
|
+
#
|
37
|
+
# @return [Shale::Adapter::<XML adapter>::Node]
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
def as_xml(doc)
|
41
|
+
complex_type = doc.create_element('xs:complexType')
|
42
|
+
|
43
|
+
doc.add_attribute(complex_type, 'name', @name)
|
44
|
+
doc.add_attribute(complex_type, 'mixed', 'true') if @mixed
|
45
|
+
|
46
|
+
elements = @children.select { |e| e.is_a?(Element) }
|
47
|
+
attributes = @children.select { |e| e.is_a?(Attribute) }
|
48
|
+
|
49
|
+
unless elements.empty?
|
50
|
+
sequence = doc.create_element('xs:sequence')
|
51
|
+
doc.add_element(complex_type, sequence)
|
52
|
+
|
53
|
+
elements.each do |element|
|
54
|
+
doc.add_element(sequence, element.as_xml(doc))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
attributes.each do |attribute|
|
59
|
+
doc.add_element(complex_type, attribute.as_xml(doc))
|
60
|
+
end
|
61
|
+
|
62
|
+
complex_type
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shale
|
4
|
+
module Schema
|
5
|
+
class XML
|
6
|
+
# Class representing XML Schema <element> element.
|
7
|
+
# Serves as a base class for TypedElement and RefElement
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
class Element
|
11
|
+
# Initialize Element object
|
12
|
+
#
|
13
|
+
# @param [String, nil] default
|
14
|
+
# @param [true, false] collection
|
15
|
+
# @param [true, false] required
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
def initialize(default, collection, required)
|
19
|
+
@default = default
|
20
|
+
@collection = collection
|
21
|
+
@required = required
|
22
|
+
end
|
23
|
+
|
24
|
+
# Append element to the XML document
|
25
|
+
#
|
26
|
+
# @param [Shale::Adapter::<XML adapter>::Document] doc
|
27
|
+
#
|
28
|
+
# @return [Shale::Adapter::<XML adapter>::Node]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def as_xml(doc)
|
32
|
+
element = doc.create_element('xs:element')
|
33
|
+
|
34
|
+
attributes.each do |name, value|
|
35
|
+
doc.add_attribute(element, name, value)
|
36
|
+
end
|
37
|
+
|
38
|
+
unless @required
|
39
|
+
doc.add_attribute(element, 'minOccurs', 0)
|
40
|
+
end
|
41
|
+
|
42
|
+
if @collection
|
43
|
+
doc.add_attribute(element, 'maxOccurs', 'unbounded')
|
44
|
+
end
|
45
|
+
|
46
|
+
unless @default.nil?
|
47
|
+
doc.add_attribute(element, 'default', @default)
|
48
|
+
end
|
49
|
+
|
50
|
+
element
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shale
|
4
|
+
module Schema
|
5
|
+
class XML
|
6
|
+
# Class representing XML Schema <import> element
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Import
|
10
|
+
# Return namespace
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
attr_reader :namespace
|
16
|
+
|
17
|
+
# Initialize Import object
|
18
|
+
#
|
19
|
+
# @param [String, nil] namespace
|
20
|
+
# @param [String, nil] location
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
def initialize(namespace, location)
|
24
|
+
@namespace = namespace
|
25
|
+
@location = location
|
26
|
+
end
|
27
|
+
|
28
|
+
# Append element to the XML document
|
29
|
+
#
|
30
|
+
# @param [Shale::Adapter::<XML adapter>::Document] doc
|
31
|
+
#
|
32
|
+
# @return [Shale::Adapter::<XML adapter>::Node]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
def as_xml(doc)
|
36
|
+
import = doc.create_element('xs:import')
|
37
|
+
|
38
|
+
doc.add_attribute(import, 'namespace', @namespace)
|
39
|
+
doc.add_attribute(import, 'schemaLocation', @location)
|
40
|
+
|
41
|
+
import
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'attribute'
|
4
|
+
|
5
|
+
module Shale
|
6
|
+
module Schema
|
7
|
+
class XML
|
8
|
+
# Class representing XML Schema <attribute ref=""> element
|
9
|
+
# with a reference
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class RefAttribute < Attribute
|
13
|
+
# Initialize RefAttribute object
|
14
|
+
#
|
15
|
+
# @param [String] ref
|
16
|
+
# @param [String, nil] default
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
def initialize(ref:, default: nil)
|
20
|
+
super(default)
|
21
|
+
@ref = ref
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Return attributes as Ruby Hash
|
27
|
+
#
|
28
|
+
# @return [Hash]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
def attributes
|
32
|
+
{ 'ref' => @ref }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|