lutaml-model 0.5.4 → 0.6.1
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/.rubocop_todo.yml +58 -21
- data/Gemfile +1 -0
- data/README.adoc +1112 -264
- data/lib/lutaml/model/attribute.rb +37 -15
- data/lib/lutaml/model/choice.rb +56 -0
- data/lib/lutaml/model/config.rb +1 -0
- data/lib/lutaml/model/error/choice_lower_bound_error.rb +9 -0
- data/lib/lutaml/model/error/choice_upper_bound_error.rb +9 -0
- data/lib/lutaml/model/error/import_model_with_root_error.rb +9 -0
- data/lib/lutaml/model/error/incorrect_sequence_error.rb +9 -0
- data/lib/lutaml/model/error/invalid_choice_range_error.rb +20 -0
- data/lib/lutaml/model/error/no_root_mapping_error.rb +9 -0
- data/lib/lutaml/model/error/no_root_namespace_error.rb +9 -0
- data/lib/lutaml/model/error/unknown_sequence_mapping_error.rb +9 -0
- data/lib/lutaml/model/error.rb +8 -0
- data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +6 -1
- data/lib/lutaml/model/key_value_mapping.rb +3 -1
- data/lib/lutaml/model/key_value_mapping_rule.rb +4 -2
- data/lib/lutaml/model/liquefiable.rb +59 -0
- data/lib/lutaml/model/mapping_hash.rb +1 -1
- data/lib/lutaml/model/mapping_rule.rb +15 -2
- data/lib/lutaml/model/schema/xml_compiler.rb +68 -26
- data/lib/lutaml/model/schema_location.rb +7 -0
- data/lib/lutaml/model/sequence.rb +71 -0
- data/lib/lutaml/model/serialize.rb +126 -38
- data/lib/lutaml/model/type/decimal.rb +0 -4
- data/lib/lutaml/model/type/time.rb +3 -3
- data/lib/lutaml/model/utils.rb +19 -15
- data/lib/lutaml/model/validation.rb +12 -1
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model/xml_adapter/builder/oga.rb +10 -7
- data/lib/lutaml/model/xml_adapter/builder/ox.rb +20 -13
- data/lib/lutaml/model/xml_adapter/element.rb +32 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +8 -8
- data/lib/lutaml/model/xml_adapter/oga/element.rb +14 -13
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +86 -19
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +19 -15
- data/lib/lutaml/model/xml_adapter/xml_document.rb +74 -13
- data/lib/lutaml/model/xml_adapter/xml_element.rb +57 -3
- data/lib/lutaml/model/xml_mapping.rb +49 -7
- data/lib/lutaml/model/xml_mapping_rule.rb +8 -3
- data/lib/lutaml/model.rb +1 -0
- data/lutaml-model.gemspec +5 -0
- data/spec/benchmarks/xml_parsing_benchmark_spec.rb +75 -0
- data/spec/ceramic_spec.rb +39 -0
- data/spec/fixtures/ceramic.rb +23 -0
- data/spec/fixtures/xml/address_example_260.xsd +9 -0
- data/spec/fixtures/xml/user.xsd +10 -0
- data/spec/lutaml/model/cdata_spec.rb +4 -5
- data/spec/lutaml/model/choice_spec.rb +168 -0
- data/spec/lutaml/model/collection_spec.rb +1 -1
- data/spec/lutaml/model/custom_model_spec.rb +55 -8
- data/spec/lutaml/model/custom_serialization_spec.rb +74 -2
- data/spec/lutaml/model/defaults_spec.rb +3 -1
- data/spec/lutaml/model/delegation_spec.rb +7 -5
- data/spec/lutaml/model/enum_spec.rb +35 -0
- data/spec/lutaml/model/group_spec.rb +160 -0
- data/spec/lutaml/model/inheritance_spec.rb +25 -0
- data/spec/lutaml/model/liquefiable_spec.rb +121 -0
- data/spec/lutaml/model/mixed_content_spec.rb +80 -41
- data/spec/lutaml/model/multiple_mapping_spec.rb +22 -10
- data/spec/lutaml/model/schema/xml_compiler_spec.rb +218 -25
- data/spec/lutaml/model/sequence_spec.rb +216 -0
- data/spec/lutaml/model/transformation_spec.rb +230 -0
- data/spec/lutaml/model/type_spec.rb +138 -31
- data/spec/lutaml/model/utils_spec.rb +32 -0
- data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -7
- data/spec/lutaml/model/xml_mapping_rule_spec.rb +51 -0
- data/spec/lutaml/model/xml_mapping_spec.rb +167 -112
- metadata +67 -2
@@ -10,6 +10,9 @@ module Lutaml
|
|
10
10
|
collection
|
11
11
|
values
|
12
12
|
pattern
|
13
|
+
transform
|
14
|
+
choice
|
15
|
+
sequence
|
13
16
|
].freeze
|
14
17
|
|
15
18
|
def initialize(name, type, options = {})
|
@@ -33,6 +36,10 @@ module Lutaml
|
|
33
36
|
@options[:delegate]
|
34
37
|
end
|
35
38
|
|
39
|
+
def transform
|
40
|
+
@options[:transform] || {}
|
41
|
+
end
|
42
|
+
|
36
43
|
def cast_type!(type)
|
37
44
|
case type
|
38
45
|
when Symbol
|
@@ -81,15 +88,17 @@ module Lutaml
|
|
81
88
|
end
|
82
89
|
|
83
90
|
def default
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
cast_value(default_value)
|
92
|
+
end
|
93
|
+
|
94
|
+
def default_value
|
95
|
+
if delegate
|
96
|
+
type.attributes[to].default
|
97
|
+
elsif options[:default].is_a?(Proc)
|
98
|
+
options[:default].call
|
99
|
+
else
|
100
|
+
options[:default]
|
101
|
+
end
|
93
102
|
end
|
94
103
|
|
95
104
|
def pattern
|
@@ -100,8 +109,16 @@ module Lutaml
|
|
100
109
|
@options.key?(:values) ? @options[:values] : []
|
101
110
|
end
|
102
111
|
|
112
|
+
def transform_import_method
|
113
|
+
transform[:import]
|
114
|
+
end
|
115
|
+
|
116
|
+
def transform_export_method
|
117
|
+
transform[:export]
|
118
|
+
end
|
119
|
+
|
103
120
|
def valid_value!(value)
|
104
|
-
return true if value.nil? &&
|
121
|
+
return true if value.nil? && singular?
|
105
122
|
return true unless enum?
|
106
123
|
|
107
124
|
unless valid_value?(value)
|
@@ -153,6 +170,10 @@ module Lutaml
|
|
153
170
|
raise ArgumentError, "Invalid collection range: #{range}"
|
154
171
|
end
|
155
172
|
|
173
|
+
validate_range!(range)
|
174
|
+
end
|
175
|
+
|
176
|
+
def validate_range!(range)
|
156
177
|
if range.begin.nil?
|
157
178
|
raise ArgumentError,
|
158
179
|
"Invalid collection range: #{range}. Begin must be specified."
|
@@ -227,14 +248,15 @@ module Lutaml
|
|
227
248
|
end
|
228
249
|
|
229
250
|
def cast(value, format, options = {})
|
230
|
-
value
|
251
|
+
return value if type <= Serialize && value.is_a?(type.model)
|
231
252
|
|
253
|
+
value ||= [] if collection?
|
232
254
|
if value.is_a?(Array)
|
233
|
-
value.map
|
234
|
-
|
235
|
-
end
|
236
|
-
elsif type <= Serialize && value.is_a?(Hash)
|
255
|
+
value.map { |v| cast(v, format, options) }
|
256
|
+
elsif type <= Serialize && (value.is_a?(Hash) || value.is_a?(Lutaml::Model::XmlAdapter::XmlElement))
|
237
257
|
type.apply_mappings(value, format, options)
|
258
|
+
elsif !value.nil? && !value.is_a?(type)
|
259
|
+
type.send(:"from_#{format}", value)
|
238
260
|
else
|
239
261
|
type.cast(value)
|
240
262
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class Choice
|
4
|
+
attr_reader :attributes,
|
5
|
+
:model,
|
6
|
+
:min,
|
7
|
+
:max
|
8
|
+
|
9
|
+
def initialize(model, min, max)
|
10
|
+
@attributes = []
|
11
|
+
@model = model
|
12
|
+
@min = min
|
13
|
+
@max = max
|
14
|
+
|
15
|
+
raise Lutaml::Model::InvalidChoiceRangeError.new(@min, @max) if @min.negative? || @max.negative?
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute(name, type, options = {})
|
19
|
+
options[:choice] = self
|
20
|
+
@attributes << @model.attribute(name, type, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def choice(min: 1, max: 1, &block)
|
24
|
+
@attributes << Choice.new(@model, min, max).tap do |c|
|
25
|
+
c.instance_eval(&block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_content!(object)
|
30
|
+
validated_attributes = []
|
31
|
+
valid = valid_attributes(object, validated_attributes)
|
32
|
+
|
33
|
+
raise Lutaml::Model::ChoiceUpperBoundError.new(validated_attributes, @max) if valid.count > @max
|
34
|
+
raise Lutaml::Model::ChoiceLowerBoundError.new(validated_attributes, @min) if valid.count < @min
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def valid_attributes(object, validated_attributes)
|
40
|
+
@attributes.each do |attribute|
|
41
|
+
if attribute.is_a?(Choice)
|
42
|
+
begin
|
43
|
+
attribute.validate_content!(object)
|
44
|
+
validated_attributes << attribute
|
45
|
+
rescue Lutaml::Model::ChoiceLowerBoundError
|
46
|
+
end
|
47
|
+
elsif Utils.present?(object.public_send(attribute.name))
|
48
|
+
validated_attributes << attribute.name
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
validated_attributes
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/lutaml/model/config.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class IncorrectSequenceError < Error
|
4
|
+
def initialize(defined_order_element, expected_order_element)
|
5
|
+
super("Element `#{expected_order_element}` does not match the expected sequence order element `#{defined_order_element}`")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Lutaml
|
2
|
+
module Model
|
3
|
+
class InvalidChoiceRangeError < Error
|
4
|
+
def initialize(min, max)
|
5
|
+
@min = min
|
6
|
+
@max = max
|
7
|
+
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
if @min.negative?
|
13
|
+
"Choice lower bound `#{@min}` must be positive"
|
14
|
+
else
|
15
|
+
"Choice upper bound `#{@max}` must be positive"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/lutaml/model/error.rb
CHANGED
@@ -17,3 +17,11 @@ require_relative "error/unknown_type_error"
|
|
17
17
|
require_relative "error/multiple_mappings_error"
|
18
18
|
require_relative "error/collection_true_missing_error"
|
19
19
|
require_relative "error/type/invalid_value_error"
|
20
|
+
require_relative "error/incorrect_sequence_error"
|
21
|
+
require_relative "error/choice_upper_bound_error"
|
22
|
+
require_relative "error/no_root_mapping_error"
|
23
|
+
require_relative "error/import_model_with_root_error"
|
24
|
+
require_relative "error/invalid_choice_range_error"
|
25
|
+
require_relative "error/unknown_sequence_mapping_error"
|
26
|
+
require_relative "error/choice_lower_bound_error"
|
27
|
+
require_relative "error/no_root_namespace_error"
|
@@ -10,7 +10,12 @@ module Lutaml
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_json(*args)
|
13
|
-
|
13
|
+
options = args.first || {}
|
14
|
+
if options[:pretty]
|
15
|
+
JSON.pretty_generate(@attributes, *args)
|
16
|
+
else
|
17
|
+
JSON.generate(@attributes, *args)
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
16
21
|
end
|
@@ -17,7 +17,8 @@ module Lutaml
|
|
17
17
|
with: {},
|
18
18
|
delegate: nil,
|
19
19
|
child_mappings: nil,
|
20
|
-
root_mappings: nil
|
20
|
+
root_mappings: nil,
|
21
|
+
transform: {}
|
21
22
|
)
|
22
23
|
mapping_name = name_for_mapping(root_mappings, name)
|
23
24
|
validate!(mapping_name, to, with)
|
@@ -31,6 +32,7 @@ module Lutaml
|
|
31
32
|
delegate: delegate,
|
32
33
|
child_mappings: child_mappings,
|
33
34
|
root_mappings: root_mappings,
|
35
|
+
transform: transform,
|
34
36
|
)
|
35
37
|
end
|
36
38
|
|
@@ -14,7 +14,8 @@ module Lutaml
|
|
14
14
|
with: {},
|
15
15
|
delegate: nil,
|
16
16
|
child_mappings: nil,
|
17
|
-
root_mappings: nil
|
17
|
+
root_mappings: nil,
|
18
|
+
transform: {}
|
18
19
|
)
|
19
20
|
super(
|
20
21
|
name,
|
@@ -22,7 +23,8 @@ module Lutaml
|
|
22
23
|
render_nil: render_nil,
|
23
24
|
render_default: render_default,
|
24
25
|
with: with,
|
25
|
-
delegate: delegate
|
26
|
+
delegate: delegate,
|
27
|
+
transform: transform
|
26
28
|
)
|
27
29
|
|
28
30
|
@child_mappings = child_mappings
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "liquid"
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module Liquefiable
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def register_liquid_drop_class
|
12
|
+
if drop_class
|
13
|
+
raise "#{drop_class_name} Already exists!"
|
14
|
+
end
|
15
|
+
|
16
|
+
const_set(drop_class_name,
|
17
|
+
Class.new(Liquid::Drop) do
|
18
|
+
def initialize(object)
|
19
|
+
super()
|
20
|
+
@object = object
|
21
|
+
end
|
22
|
+
end)
|
23
|
+
end
|
24
|
+
|
25
|
+
def drop_class_name
|
26
|
+
@drop_class_name ||= if name
|
27
|
+
"#{to_s.split('::').last}Drop"
|
28
|
+
else
|
29
|
+
"Drop"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def drop_class
|
34
|
+
const_get(drop_class_name)
|
35
|
+
rescue StandardError
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def register_drop_method(method_name)
|
40
|
+
register_liquid_drop_class unless drop_class
|
41
|
+
|
42
|
+
drop_class.define_method(method_name) do
|
43
|
+
value = @object.public_send(method_name)
|
44
|
+
|
45
|
+
if value.is_a?(Array)
|
46
|
+
value.map(&:to_liquid)
|
47
|
+
else
|
48
|
+
value.to_liquid
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_liquid
|
55
|
+
self.class.drop_class.new(self)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -7,7 +7,8 @@ module Lutaml
|
|
7
7
|
:render_default,
|
8
8
|
:attribute,
|
9
9
|
:custom_methods,
|
10
|
-
:delegate
|
10
|
+
:delegate,
|
11
|
+
:transform
|
11
12
|
|
12
13
|
def initialize(
|
13
14
|
name,
|
@@ -17,7 +18,8 @@ module Lutaml
|
|
17
18
|
with: {},
|
18
19
|
attribute: false,
|
19
20
|
delegate: nil,
|
20
|
-
root_mappings: nil
|
21
|
+
root_mappings: nil,
|
22
|
+
transform: {}
|
21
23
|
)
|
22
24
|
@name = name
|
23
25
|
@to = to
|
@@ -27,6 +29,7 @@ module Lutaml
|
|
27
29
|
@attribute = attribute
|
28
30
|
@delegate = delegate
|
29
31
|
@root_mappings = root_mappings
|
32
|
+
@transform = transform
|
30
33
|
end
|
31
34
|
|
32
35
|
alias from name
|
@@ -71,6 +74,8 @@ module Lutaml
|
|
71
74
|
end
|
72
75
|
|
73
76
|
model.public_send(delegate).public_send(:"#{to}=", value)
|
77
|
+
elsif transform_method = transform[:import] || attributes[to].transform_import_method
|
78
|
+
model.public_send(:"#{to}=", transform_method.call(value))
|
74
79
|
else
|
75
80
|
model.public_send(:"#{to}=", value)
|
76
81
|
end
|
@@ -88,6 +93,14 @@ module Lutaml
|
|
88
93
|
name == Constants::RAW_MAPPING_KEY
|
89
94
|
end
|
90
95
|
|
96
|
+
def eql?(other)
|
97
|
+
other.class == self.class &&
|
98
|
+
instance_variables.all? do |var|
|
99
|
+
instance_variable_get(var) == other.instance_variable_get(var)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
alias == eql?
|
103
|
+
|
91
104
|
def deep_dup
|
92
105
|
raise NotImplementedError, "Subclasses must implement `deep_dup`."
|
93
106
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "erb"
|
4
|
+
require "tmpdir"
|
4
5
|
require "lutaml/xsd"
|
5
6
|
require_relative "templates/simple_type"
|
6
7
|
|
@@ -37,7 +38,7 @@ module Lutaml
|
|
37
38
|
if content&.key_exist?(:sequence) || content&.key_exist?(:choice) || content&.key_exist?(:group)
|
38
39
|
output = resolve_content(content).map do |element_name, element|
|
39
40
|
element = @elements[element.ref_class.split(":")&.last] if element&.key_exist?(:ref_class)
|
40
|
-
" attribute :\#{Utils.snake_case(element_name)}, \#{
|
41
|
+
" attribute :\#{Utils.snake_case(element_name)}, \#{resolve_element_class(element)}\#{resolve_occurs(element.arguments) if element.key_exist?(:arguments)}"
|
41
42
|
end.join("\n")
|
42
43
|
output + "\n" if output && !output&.empty?
|
43
44
|
end
|
@@ -49,13 +50,13 @@ module Lutaml
|
|
49
50
|
element.map { |attribute| " attribute :\#{Utils.snake_case(attribute.name)}, \#{resolve_attribute_class(attribute)}\#{resolve_attribute_default(attribute.default) if attribute.key_exist?(:default)}" }.join("\n")
|
50
51
|
else
|
51
52
|
element = @elements[element.ref_class.split(":")&.last] if element&.key_exist?(:ref_class)
|
52
|
-
" attribute :\#{Utils.snake_case(element_name)}, \#{
|
53
|
+
" attribute :\#{Utils.snake_case(element_name)}, \#{resolve_element_class(element)}\#{resolve_occurs(element.arguments) if element.key_exist?(:arguments)}"
|
53
54
|
end
|
54
55
|
end.join("\n")
|
55
56
|
output + "\n" if output && !output&.empty?
|
56
57
|
end
|
57
58
|
-%>
|
58
|
-
<%= " attribute :content, \#{content.simple_content.extension_base}" if content_exist = content.key_exist?(:simple_content) && content.simple_content.key_exist?(:extension_base) -%>
|
59
|
+
<%= " attribute :content, \#{content[:mixed] ? ':string' : content.simple_content.extension_base}" if content_exist = (content.key_exist?(:simple_content) && content.simple_content.key_exist?(:extension_base)) || content[:mixed] -%>
|
59
60
|
|
60
61
|
xml do
|
61
62
|
root "<%= name %>", mixed: true
|
@@ -107,13 +108,28 @@ module Lutaml
|
|
107
108
|
|
108
109
|
def to_models(schema, options = {})
|
109
110
|
as_models(schema, options: options)
|
110
|
-
dir = options.fetch(:output_dir, "lutaml_models_#{Time.now.to_i}")
|
111
|
-
FileUtils.mkdir_p(dir)
|
112
|
-
|
113
111
|
@data_types_classes = Templates::SimpleType.create_simple_types(@simple_types)
|
114
|
-
|
115
|
-
|
116
|
-
|
112
|
+
if options[:create_files]
|
113
|
+
dir = options.fetch(:output_dir, "lutaml_models_#{Time.now.to_i}")
|
114
|
+
FileUtils.mkdir_p(dir)
|
115
|
+
@data_types_classes.each do |name, content|
|
116
|
+
create_file(name, content, dir)
|
117
|
+
end
|
118
|
+
@complex_types.each do |name, content|
|
119
|
+
create_file(name, MODEL_TEMPLATE.result(binding), dir)
|
120
|
+
end
|
121
|
+
nil
|
122
|
+
else
|
123
|
+
simple_types = @data_types_classes.transform_keys do |key|
|
124
|
+
Utils.camel_case(key.to_s)
|
125
|
+
end
|
126
|
+
complex_types = @complex_types.to_h do |name, content|
|
127
|
+
[Utils.camel_case(name), MODEL_TEMPLATE.result(binding)]
|
128
|
+
end
|
129
|
+
classes_hash = simple_types.merge(complex_types)
|
130
|
+
require_classes(classes_hash) if options[:load_classes]
|
131
|
+
classes_hash
|
132
|
+
end
|
117
133
|
end
|
118
134
|
|
119
135
|
private
|
@@ -122,6 +138,15 @@ module Lutaml
|
|
122
138
|
File.write("#{dir}/#{Utils.snake_case(name)}.rb", content)
|
123
139
|
end
|
124
140
|
|
141
|
+
def require_classes(classes_hash)
|
142
|
+
Dir.mktmpdir do |dir|
|
143
|
+
classes_hash.each do |name, klass|
|
144
|
+
create_file(name, klass, dir)
|
145
|
+
require "#{dir}/#{Utils.snake_case(name)}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
125
150
|
# START: STRUCTURE SETUP METHODS
|
126
151
|
|
127
152
|
def as_models(schema, options: {})
|
@@ -136,7 +161,7 @@ module Lutaml
|
|
136
161
|
@complex_types = MappingHash.new
|
137
162
|
@attribute_groups = MappingHash.new
|
138
163
|
|
139
|
-
schema_to_models(
|
164
|
+
schema_to_models(Array(parsed_schema))
|
140
165
|
end
|
141
166
|
|
142
167
|
def schema_to_models(schemas)
|
@@ -196,6 +221,7 @@ module Lutaml
|
|
196
221
|
MappingHash.new.tap do |hash|
|
197
222
|
hash[:attributes] = [] if complex_type.attribute.any?
|
198
223
|
hash[:attribute_groups] = [] if complex_type.attribute_group.any?
|
224
|
+
hash[:mixed] = complex_type.mixed
|
199
225
|
resolved_element_order(complex_type).each do |element|
|
200
226
|
case element
|
201
227
|
when Xsd::Attribute
|
@@ -237,18 +263,18 @@ module Lutaml
|
|
237
263
|
hash[:sequences] << setup_sequence(instance)
|
238
264
|
when Xsd::Element
|
239
265
|
hash[:elements] << if instance.name
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
266
|
+
setup_element(instance)
|
267
|
+
else
|
268
|
+
create_mapping_hash(instance.ref, hash_key: :ref_class)
|
269
|
+
end
|
244
270
|
when Xsd::Choice
|
245
271
|
hash[:choice] << setup_choice(instance)
|
246
272
|
when Xsd::Group
|
247
273
|
hash[:groups] << if instance.name
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
274
|
+
setup_group_type(instance)
|
275
|
+
else
|
276
|
+
create_mapping_hash(instance.ref, hash_key: :ref_class)
|
277
|
+
end
|
252
278
|
when Xsd::Any
|
253
279
|
# No implementation yet!
|
254
280
|
end
|
@@ -363,7 +389,7 @@ module Lutaml
|
|
363
389
|
def restriction_patterns(patterns, hash)
|
364
390
|
return if patterns.empty?
|
365
391
|
|
366
|
-
hash[:pattern] = patterns.map { |
|
392
|
+
hash[:pattern] = patterns.map { |p| "(#{p.value})" }.join("|")
|
367
393
|
hash
|
368
394
|
end
|
369
395
|
|
@@ -404,22 +430,23 @@ module Lutaml
|
|
404
430
|
end
|
405
431
|
end
|
406
432
|
|
407
|
-
def resolved_element_order(object
|
433
|
+
def resolved_element_order(object)
|
408
434
|
return [] if object.element_order.nil?
|
409
435
|
|
410
|
-
object.element_order.each_with_object(object.element_order.dup) do |
|
411
|
-
next array.delete(
|
412
|
-
next array.delete(
|
436
|
+
object.element_order.each_with_object(object.element_order.dup) do |builder_instance, array|
|
437
|
+
next array.delete(builder_instance) if builder_instance.text?
|
438
|
+
next array.delete(builder_instance) if ELEMENT_ORDER_IGNORABLE.include?(builder_instance.name)
|
413
439
|
|
414
440
|
index = 0
|
415
441
|
array.each_with_index do |element, i|
|
416
|
-
next unless element ==
|
442
|
+
next unless element == builder_instance
|
417
443
|
|
418
|
-
array[i] = Array(object.send(Utils.snake_case(name)))[index]
|
444
|
+
array[i] = Array(object.send(Utils.snake_case(builder_instance.name)))[index]
|
419
445
|
index += 1
|
420
446
|
end
|
421
447
|
end
|
422
448
|
end
|
449
|
+
|
423
450
|
# END: STRUCTURE SETUP METHODS
|
424
451
|
|
425
452
|
# START: TEMPLATE RESOLVER METHODS
|
@@ -439,6 +466,16 @@ module Lutaml
|
|
439
466
|
end
|
440
467
|
end
|
441
468
|
|
469
|
+
def resolve_element_class(element)
|
470
|
+
element_class = element.type_name.split(":").last
|
471
|
+
case element_class
|
472
|
+
when *DEFAULT_CLASSES
|
473
|
+
":#{element_class}"
|
474
|
+
else
|
475
|
+
Utils.camel_case(element_class)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
442
479
|
def resolve_occurs(arguments)
|
443
480
|
min_occurs = arguments[:min_occurs]
|
444
481
|
max_occurs = arguments[:max_occurs]
|
@@ -583,6 +620,7 @@ module Lutaml
|
|
583
620
|
end
|
584
621
|
@required_files.uniq.sort_by(&:length)
|
585
622
|
end
|
623
|
+
|
586
624
|
# END: TEMPLATE RESOLVER METHODS
|
587
625
|
|
588
626
|
# START: REQUIRED FILES LIST COMPILER METHODS
|
@@ -710,9 +748,13 @@ module Lutaml
|
|
710
748
|
def required_files_elements(elements)
|
711
749
|
elements.each do |element|
|
712
750
|
element = @elements[element.ref_class.split(":").last] if element.key_exist?(:ref_class)
|
713
|
-
|
751
|
+
element_class = element.type_name.split(":").last
|
752
|
+
next if DEFAULT_CLASSES.include?(element_class)
|
753
|
+
|
754
|
+
@required_files << Utils.snake_case(element_class)
|
714
755
|
end
|
715
756
|
end
|
757
|
+
|
716
758
|
# END: REQUIRED FILES LIST COMPILER METHODS
|
717
759
|
end
|
718
760
|
end
|
@@ -11,6 +11,13 @@ module Lutaml
|
|
11
11
|
def to_xml_attribute
|
12
12
|
"#{@namespace} #{@location}".strip
|
13
13
|
end
|
14
|
+
|
15
|
+
def eql?(other)
|
16
|
+
other.class == self.class &&
|
17
|
+
namespace == other.namespace &&
|
18
|
+
location == other.location
|
19
|
+
end
|
20
|
+
alias == eql?
|
14
21
|
end
|
15
22
|
|
16
23
|
class SchemaLocation
|