lutaml-model 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +58 -21
  3. data/Gemfile +1 -0
  4. data/README.adoc +1112 -264
  5. data/lib/lutaml/model/attribute.rb +33 -10
  6. data/lib/lutaml/model/choice.rb +56 -0
  7. data/lib/lutaml/model/config.rb +1 -0
  8. data/lib/lutaml/model/error/choice_lower_bound_error.rb +9 -0
  9. data/lib/lutaml/model/error/choice_upper_bound_error.rb +9 -0
  10. data/lib/lutaml/model/error/import_model_with_root_error.rb +9 -0
  11. data/lib/lutaml/model/error/incorrect_sequence_error.rb +9 -0
  12. data/lib/lutaml/model/error/invalid_choice_range_error.rb +20 -0
  13. data/lib/lutaml/model/error/no_root_mapping_error.rb +9 -0
  14. data/lib/lutaml/model/error/no_root_namespace_error.rb +9 -0
  15. data/lib/lutaml/model/error/unknown_sequence_mapping_error.rb +9 -0
  16. data/lib/lutaml/model/error.rb +8 -0
  17. data/lib/lutaml/model/json_adapter/standard_json_adapter.rb +6 -1
  18. data/lib/lutaml/model/key_value_mapping.rb +3 -1
  19. data/lib/lutaml/model/key_value_mapping_rule.rb +4 -2
  20. data/lib/lutaml/model/liquefiable.rb +59 -0
  21. data/lib/lutaml/model/mapping_hash.rb +1 -1
  22. data/lib/lutaml/model/mapping_rule.rb +15 -2
  23. data/lib/lutaml/model/schema/xml_compiler.rb +68 -26
  24. data/lib/lutaml/model/schema_location.rb +7 -0
  25. data/lib/lutaml/model/sequence.rb +71 -0
  26. data/lib/lutaml/model/serialize.rb +125 -35
  27. data/lib/lutaml/model/type/decimal.rb +0 -4
  28. data/lib/lutaml/model/type/time.rb +3 -3
  29. data/lib/lutaml/model/utils.rb +19 -15
  30. data/lib/lutaml/model/validation.rb +12 -1
  31. data/lib/lutaml/model/version.rb +1 -1
  32. data/lib/lutaml/model/xml_adapter/builder/oga.rb +10 -7
  33. data/lib/lutaml/model/xml_adapter/builder/ox.rb +20 -13
  34. data/lib/lutaml/model/xml_adapter/element.rb +32 -0
  35. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +8 -8
  36. data/lib/lutaml/model/xml_adapter/oga/element.rb +14 -13
  37. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +86 -19
  38. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +19 -15
  39. data/lib/lutaml/model/xml_adapter/xml_document.rb +74 -13
  40. data/lib/lutaml/model/xml_adapter/xml_element.rb +57 -3
  41. data/lib/lutaml/model/xml_mapping.rb +49 -7
  42. data/lib/lutaml/model/xml_mapping_rule.rb +8 -3
  43. data/lib/lutaml/model.rb +1 -0
  44. data/lutaml-model.gemspec +5 -0
  45. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +75 -0
  46. data/spec/ceramic_spec.rb +39 -0
  47. data/spec/fixtures/ceramic.rb +23 -0
  48. data/spec/fixtures/xml/address_example_260.xsd +9 -0
  49. data/spec/fixtures/xml/user.xsd +10 -0
  50. data/spec/lutaml/model/cdata_spec.rb +4 -5
  51. data/spec/lutaml/model/choice_spec.rb +168 -0
  52. data/spec/lutaml/model/collection_spec.rb +1 -1
  53. data/spec/lutaml/model/custom_model_spec.rb +6 -7
  54. data/spec/lutaml/model/custom_serialization_spec.rb +74 -2
  55. data/spec/lutaml/model/defaults_spec.rb +3 -1
  56. data/spec/lutaml/model/delegation_spec.rb +7 -5
  57. data/spec/lutaml/model/enum_spec.rb +35 -0
  58. data/spec/lutaml/model/group_spec.rb +160 -0
  59. data/spec/lutaml/model/inheritance_spec.rb +25 -0
  60. data/spec/lutaml/model/liquefiable_spec.rb +121 -0
  61. data/spec/lutaml/model/mixed_content_spec.rb +80 -41
  62. data/spec/lutaml/model/multiple_mapping_spec.rb +22 -10
  63. data/spec/lutaml/model/schema/xml_compiler_spec.rb +218 -25
  64. data/spec/lutaml/model/sequence_spec.rb +216 -0
  65. data/spec/lutaml/model/transformation_spec.rb +230 -0
  66. data/spec/lutaml/model/type_spec.rb +138 -31
  67. data/spec/lutaml/model/utils_spec.rb +32 -0
  68. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +11 -7
  69. data/spec/lutaml/model/xml_mapping_rule_spec.rb +51 -0
  70. data/spec/lutaml/model/xml_mapping_spec.rb +143 -112
  71. 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
- value = if delegate
85
- type.attributes[to].default
86
- elsif options[:default].is_a?(Proc)
87
- options[:default].call
88
- else
89
- options[:default]
90
- end
91
-
92
- cast_value(value)
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? && !collection?
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."
@@ -235,6 +256,8 @@ module Lutaml
235
256
  end
236
257
  elsif type <= Serialize && value.is_a?(Hash)
237
258
  type.apply_mappings(value, format, options)
259
+ elsif !value.nil? && !value.is_a?(type)
260
+ type.send(:"from_#{format}", value)
238
261
  else
239
262
  type.cast(value)
240
263
  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
@@ -59,6 +59,7 @@ module Lutaml
59
59
  cause: nil,
60
60
  )
61
61
  end
62
+ Moxml::Adapter.load(type_name) unless KEY_VALUE_FORMATS.include?(adapter_name)
62
63
 
63
64
  instance_variable_set(
64
65
  :"@#{adapter}",
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class ChoiceLowerBoundError < Error
4
+ def initialize(validated_attributes, min)
5
+ super("Attributes `#{validated_attributes}` count is less than the lower bound `#{min}`")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class ChoiceUpperBoundError < Error
4
+ def initialize(validated_attributes, max)
5
+ super("Attributes `#{validated_attributes}` count exceeds the upper bound `#{max}`")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class ImportModelWithRootError < Error
4
+ def initialize(model)
5
+ super("Cannot import a model `#{model}` with a root element")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class NoRootMappingError < Error
4
+ def initialize(model)
5
+ super("#{model} has `no_root`, it allowed only for reusable models")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class NoRootNamespaceError < Error
4
+ def to_s
5
+ "Cannot assign namespace to `no_root`"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class UnknownSequenceMappingError < Error
4
+ def initialize(method_name)
5
+ super("#{method_name} is not allowed in sequence")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -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
- JSON.generate(@attributes, *args)
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
@@ -11,7 +11,7 @@ module Lutaml
11
11
  end
12
12
 
13
13
  def item_order
14
- @item_order&.map { |key| normalize(key) } || keys
14
+ @item_order
15
15
  end
16
16
 
17
17
  def fetch(key)
@@ -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)}, \#{Utils.camel_case(element.type_name.split(":").last)}\#{resolve_occurs(element.arguments) if element.key_exist?(:arguments)}"
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)}, \#{Utils.camel_case(element.type_name.split(":").last)}\#{resolve_occurs(element.arguments) if element.key_exist?(:arguments)}"
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
- @data_types_classes.each { |name, content| create_file(name, content, dir) }
115
- @complex_types.each { |name, content| create_file(name, MODEL_TEMPLATE.result(binding), dir) }
116
- nil
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([parsed_schema])
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
- setup_element(instance)
241
- else
242
- create_mapping_hash(instance.ref, hash_key: :ref_class)
243
- end
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
- setup_group_type(instance)
249
- else
250
- create_mapping_hash(instance.ref, hash_key: :ref_class)
251
- end
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 { |pattern| "(#{pattern.value})" }.join("|")
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, ignore_text: true)
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 |name, array|
411
- next array.delete(name) if name == "text" && (ignore_text || !object.respond_to?(:text))
412
- next array.delete(name) if ELEMENT_ORDER_IGNORABLE.include?(name)
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 == name
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
- @required_files << Utils.snake_case(element.type_name.split(":").last)
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