lutaml-model 0.8.17 → 0.8.18

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.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/downstream-performance.yml +27 -1
  3. data/.github/workflows/js-pr-check.yml +102 -0
  4. data/.github/workflows/js-sync.yml +51 -0
  5. data/.github/workflows/opal.yml +26 -6
  6. data/.github/workflows/performance.yml +32 -7
  7. data/.github/workflows/rake.yml +78 -32
  8. data/.gitmodules +6 -0
  9. data/.rubocop_todo.yml +8 -0
  10. data/Gemfile +16 -1
  11. data/README.adoc +267 -0
  12. data/Rakefile +166 -4
  13. data/docs/_guides/schema-import.adoc +42 -0
  14. data/docs/_guides/xml-mapping.adoc +21 -0
  15. data/docs/_pages/validation.adoc +65 -0
  16. data/lib/compat/opal/generate_boot.rb +123 -0
  17. data/lib/compat/opal/js_bundle_entry.rb +42 -0
  18. data/lib/compat/opal/lutaml_model_boot.rb +497 -0
  19. data/lib/compat/opal/moxml_boot.rb +68 -0
  20. data/lib/compat/opal/yaml_compat.rb +32 -0
  21. data/lib/lutaml/json.rb +1 -1
  22. data/lib/lutaml/key_value/transform.rb +3 -8
  23. data/lib/lutaml/key_value/transformation/value_serializer.rb +14 -1
  24. data/lib/lutaml/key_value/transformation.rb +17 -5
  25. data/lib/lutaml/model/adapter_resolver.rb +2 -2
  26. data/lib/lutaml/model/attribute.rb +88 -11
  27. data/lib/lutaml/model/cached_type_resolver.rb +1 -1
  28. data/lib/lutaml/model/error/union_schema_unsupported_error.rb +11 -0
  29. data/lib/lutaml/model/global_context.rb +11 -8
  30. data/lib/lutaml/model/instrumentation.rb +2 -2
  31. data/lib/lutaml/model/mapping/mapping_rule.rb +0 -6
  32. data/lib/lutaml/model/register.rb +2 -2
  33. data/lib/lutaml/model/runtime_compatibility.rb +50 -0
  34. data/lib/lutaml/model/schema/class_loader.rb +58 -0
  35. data/lib/lutaml/model/schema/compiled_output.rb +83 -0
  36. data/lib/lutaml/model/schema/definitions/attribute.rb +32 -0
  37. data/lib/lutaml/model/schema/definitions/choice.rb +20 -0
  38. data/lib/lutaml/model/schema/definitions/facet.rb +40 -0
  39. data/lib/lutaml/model/schema/definitions/group_import.rb +22 -0
  40. data/lib/lutaml/model/schema/definitions/member_walk.rb +33 -0
  41. data/lib/lutaml/model/schema/definitions/model.rb +40 -0
  42. data/lib/lutaml/model/schema/definitions/namespace.rb +23 -0
  43. data/lib/lutaml/model/schema/definitions/restricted_type.rb +30 -0
  44. data/lib/lutaml/model/schema/definitions/sequence.rb +19 -0
  45. data/lib/lutaml/model/schema/definitions/simple_content.rb +22 -0
  46. data/lib/lutaml/model/schema/definitions/transform_facet.rb +21 -0
  47. data/lib/lutaml/model/schema/definitions/type_ref.rb +20 -0
  48. data/lib/lutaml/model/schema/definitions/union_type.rb +28 -0
  49. data/lib/lutaml/model/schema/definitions/xml_root.rb +20 -0
  50. data/lib/lutaml/model/schema/definitions.rb +24 -0
  51. data/lib/lutaml/model/schema/file_writer.rb +70 -0
  52. data/lib/lutaml/model/schema/generator/definitions_collection.rb +16 -2
  53. data/lib/lutaml/model/schema/generator/property.rb +21 -4
  54. data/lib/lutaml/model/schema/module_nesting.rb +31 -0
  55. data/lib/lutaml/model/schema/namespace_naming.rb +46 -0
  56. data/lib/lutaml/model/schema/registry_generator.rb +115 -0
  57. data/lib/lutaml/model/schema/renderers/base.rb +40 -0
  58. data/lib/lutaml/model/schema/renderers/mappings.rb +72 -0
  59. data/lib/lutaml/model/schema/renderers/member_decls.rb +115 -0
  60. data/lib/lutaml/model/schema/renderers/model.rb +121 -0
  61. data/lib/lutaml/model/schema/renderers/namespace.rb +30 -0
  62. data/lib/lutaml/model/schema/renderers/registration.rb +64 -0
  63. data/lib/lutaml/model/schema/renderers/required_files_calculator.rb +93 -0
  64. data/lib/lutaml/model/schema/renderers/restricted_type.rb +88 -0
  65. data/lib/lutaml/model/schema/renderers/union.rb +83 -0
  66. data/lib/lutaml/model/schema/renderers.rb +19 -0
  67. data/lib/lutaml/model/schema/rnc_compiler/source_resolver.rb +47 -0
  68. data/lib/lutaml/model/schema/rnc_compiler.rb +62 -0
  69. data/lib/lutaml/model/schema/rng_compiler/define_classifier.rb +91 -0
  70. data/lib/lutaml/model/schema/rng_compiler/element_visitor.rb +392 -0
  71. data/lib/lutaml/model/schema/rng_compiler/member_collector.rb +30 -0
  72. data/lib/lutaml/model/schema/rng_compiler/rng_helpers.rb +152 -0
  73. data/lib/lutaml/model/schema/rng_compiler/value_type_resolver.rb +125 -0
  74. data/lib/lutaml/model/schema/rng_compiler.rb +220 -0
  75. data/lib/lutaml/model/schema/templates.rb +162 -0
  76. data/lib/lutaml/model/schema/xml_compiler/element_order.rb +41 -0
  77. data/lib/lutaml/model/schema/xml_compiler/registry_generator.rb +31 -107
  78. data/lib/lutaml/model/schema/xml_compiler/spec_builder/complex_types.rb +191 -0
  79. data/lib/lutaml/model/schema/xml_compiler/spec_builder/members.rb +216 -0
  80. data/lib/lutaml/model/schema/xml_compiler/spec_builder/simple_types.rb +153 -0
  81. data/lib/lutaml/model/schema/xml_compiler/spec_builder.rb +167 -0
  82. data/lib/lutaml/model/schema/xml_compiler/supported_data_types.rb +87 -0
  83. data/lib/lutaml/model/schema/xml_compiler.rb +38 -517
  84. data/lib/lutaml/model/schema.rb +19 -0
  85. data/lib/lutaml/model/serialize/attribute_definition.rb +14 -2
  86. data/lib/lutaml/model/serialize/builder.rb +15 -2
  87. data/lib/lutaml/model/serialize/value_mapping.rb +9 -57
  88. data/lib/lutaml/model/serialize.rb +6 -9
  89. data/lib/lutaml/model/services/rule_value_extractor.rb +2 -3
  90. data/lib/lutaml/model/services.rb +0 -2
  91. data/lib/lutaml/model/store.rb +2 -1
  92. data/lib/lutaml/model/toml.rb +1 -1
  93. data/lib/lutaml/model/transform.rb +17 -39
  94. data/lib/lutaml/model/transformation_registry.rb +1 -1
  95. data/lib/lutaml/model/type.rb +1 -0
  96. data/lib/lutaml/model/union.rb +320 -0
  97. data/lib/lutaml/model/utils.rb +6 -0
  98. data/lib/lutaml/model/validation.rb +1 -4
  99. data/lib/lutaml/model/version.rb +1 -1
  100. data/lib/lutaml/model.rb +18 -0
  101. data/lib/lutaml/toml.rb +1 -1
  102. data/lib/lutaml/xml/adapter.rb +1 -1
  103. data/lib/lutaml/xml/adapter_loader.rb +1 -1
  104. data/lib/lutaml/xml/builder/base.rb +1 -1
  105. data/lib/lutaml/xml/builder.rb +1 -1
  106. data/lib/lutaml/xml/error/schema_validation_error.rb +25 -0
  107. data/lib/lutaml/xml/model_transform.rb +5 -1
  108. data/lib/lutaml/xml/schema/relaxng_schema.rb +5 -0
  109. data/lib/lutaml/xml/schema/xsd_schema.rb +4 -0
  110. data/lib/lutaml/xml/serialization/format_conversion.rb +48 -0
  111. data/lib/lutaml/xml/serialization/instance_methods.rb +13 -0
  112. data/lib/lutaml/xml/transformation/element_builder.rb +21 -8
  113. data/lib/lutaml/xml/transformation/ordered_applier.rb +6 -0
  114. data/lib/lutaml/xml/xsd_validator.rb +66 -0
  115. data/lib/lutaml/xml.rb +53 -12
  116. data/lutaml-model.gemspec +4 -2
  117. data/spec/fixtures/xml/schema/rnc/address_book.rnc +15 -0
  118. data/spec/fixtures/xml/schema/rnc/book_features.rnc +18 -0
  119. data/spec/fixtures/xml/schema/rnc/includes/book.rnc +6 -0
  120. data/spec/fixtures/xml/schema/rnc/includes/circular_a.rnc +8 -0
  121. data/spec/fixtures/xml/schema/rnc/includes/circular_b.rnc +8 -0
  122. data/spec/fixtures/xml/schema/rnc/includes/library.rnc +8 -0
  123. data/spec/fixtures/xml/schema/rng/address_book.rng +16 -0
  124. data/spec/fixtures/xml/schema/rng/book.rng +27 -0
  125. data/spec/fixtures/xml/schema/rng/fixed_value.rng +11 -0
  126. data/spec/fixtures/xml/schema/rng/fragment_in_choice.rng +30 -0
  127. data/spec/fixtures/xml/schema/rng/full_name.rng +39 -0
  128. data/spec/fixtures/xml/schema/rng/integer_range.rng +32 -0
  129. data/spec/fixtures/xml/schema/rng/list_type.rng +12 -0
  130. data/spec/fixtures/xml/schema/rng/namespaced.rng +9 -0
  131. data/spec/fixtures/xml/schema/rng/paragraph.rng +13 -0
  132. data/spec/fixtures/xml/schema/rng/person.rng +23 -0
  133. data/spec/fixtures/xml/schema/rng/union.rng +14 -0
  134. data/spec/fixtures/xml/validate_xml_with_address.xsd +13 -0
  135. data/spec/fixtures/xml/validate_xml_with_contact.xsd +11 -0
  136. data/spec/fixtures/xml/validate_xml_with_person.xsd +11 -0
  137. data/spec/fixtures/xml/validate_xml_with_person_strict.xsd +17 -0
  138. data/spec/fixtures/xml/validate_xml_with_product.xsd +37 -0
  139. data/spec/lutaml/model/attribute_apply_value_map_spec.rb +134 -0
  140. data/spec/lutaml/model/attribute_spec.rb +169 -12
  141. data/spec/lutaml/model/boot_manifest_spec.rb +30 -0
  142. data/spec/lutaml/model/collection_spec.rb +18 -0
  143. data/spec/lutaml/model/mixed_content_spec.rb +171 -0
  144. data/spec/lutaml/model/opal_smoke_spec.rb +67 -2
  145. data/spec/lutaml/model/ordered_content_spec.rb +30 -0
  146. data/spec/lutaml/model/raw_element_spec.rb +125 -0
  147. data/spec/lutaml/model/rule_value_extractor_spec.rb +7 -14
  148. data/spec/lutaml/model/runtime_compatibility_spec.rb +25 -0
  149. data/spec/lutaml/model/schema/renderers/model_spec.rb +149 -0
  150. data/spec/lutaml/model/schema/renderers/namespace_spec.rb +36 -0
  151. data/spec/lutaml/model/schema/renderers/restricted_type_spec.rb +75 -0
  152. data/spec/lutaml/model/schema/renderers/union_spec.rb +58 -0
  153. data/spec/lutaml/model/transform_apply_value_map_spec.rb +64 -0
  154. data/spec/lutaml/model/union_attribute_spec.rb +658 -0
  155. data/spec/lutaml/model/union_spec.rb +257 -0
  156. data/spec/lutaml/model/utils_spec.rb +14 -0
  157. data/spec/lutaml/xml/opal_xml_spec.rb +22 -20
  158. data/spec/lutaml/xml/schema/compiler_spec.rb +21 -4
  159. data/spec/lutaml/xml/schema/rnc_compiler_spec.rb +404 -0
  160. data/spec/lutaml/xml/schema/rng_compiler_spec.rb +893 -0
  161. data/spec/lutaml/xml/validate_xml_with_constructs_spec.rb +222 -0
  162. data/spec/lutaml/xml/validate_xml_with_spec.rb +186 -0
  163. data/spec/spec_helper.rb +28 -11
  164. data/spec/support/opal.rb +5 -2
  165. metadata +97 -31
  166. data/lib/lutaml/model/schema/xml_compiler/attribute.rb +0 -106
  167. data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +0 -47
  168. data/lib/lutaml/model/schema/xml_compiler/choice.rb +0 -67
  169. data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +0 -27
  170. data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +0 -34
  171. data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +0 -173
  172. data/lib/lutaml/model/schema/xml_compiler/element.rb +0 -121
  173. data/lib/lutaml/model/schema/xml_compiler/group.rb +0 -113
  174. data/lib/lutaml/model/schema/xml_compiler/restriction.rb +0 -104
  175. data/lib/lutaml/model/schema/xml_compiler/sequence.rb +0 -52
  176. data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +0 -40
  177. data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +0 -265
  178. data/lib/lutaml/model/schema/xml_compiler/xml_namespace_class.rb +0 -110
  179. data/lib/lutaml/model/services/default_value_resolver.rb +0 -60
  180. data/spec/lutaml/model/services/default_value_resolver_spec.rb +0 -162
  181. data/spec/lutaml/xml/schema/compiler/attribute_group_spec.rb +0 -71
  182. data/spec/lutaml/xml/schema/compiler/attribute_spec.rb +0 -67
  183. data/spec/lutaml/xml/schema/compiler/choice_spec.rb +0 -74
  184. data/spec/lutaml/xml/schema/compiler/complex_content_restriction_spec.rb +0 -60
  185. data/spec/lutaml/xml/schema/compiler/complex_content_spec.rb +0 -41
  186. data/spec/lutaml/xml/schema/compiler/complex_type_spec.rb +0 -202
  187. data/spec/lutaml/xml/schema/compiler/element_spec.rb +0 -68
  188. data/spec/lutaml/xml/schema/compiler/group_spec.rb +0 -90
  189. data/spec/lutaml/xml/schema/compiler/restriction_spec.rb +0 -77
  190. data/spec/lutaml/xml/schema/compiler/sequence_spec.rb +0 -65
  191. data/spec/lutaml/xml/schema/compiler/simple_content_spec.rb +0 -61
  192. data/spec/lutaml/xml/schema/compiler/simple_type_spec.rb +0 -184
@@ -1,173 +0,0 @@
1
- module Lutaml
2
- module Model
3
- module Schema
4
- module XmlCompiler
5
- class ComplexType
6
- attr_accessor :id,
7
- :name,
8
- :mixed,
9
- :instances,
10
- :base_class,
11
- :simple_content
12
-
13
- SERIALIZABLE_BASE_CLASS = "Lutaml::Model::Serializable".freeze
14
-
15
- SIMPLE_CONTENT_ATTRIBUTE_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
16
- <%= @indent %>attribute :content, :<%= simple_content_type %><%= ", collection: true" if mixed && !simple_content? %>
17
- <%= simple_content.to_attributes(@indent) if simple_content? -%>
18
- TEMPLATE
19
-
20
- TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
21
- # frozen_string_literal: true
22
-
23
- require "lutaml/model"
24
- <%= required_files.uniq.join("\n") + "\n" -%>
25
- <%= module_opening -%>
26
- class <%= Utils.camel_case(name) %> < <%= base_class_name %>
27
- <%= instances.flat_map { |instance| instance.to_attributes(@indent) }.join + "\n" -%>
28
- <%= simple_content_attribute -%>
29
- <%= @indent %>xml do
30
- <%= extended_indent %>element "<%= name %>"
31
- <%= extended_indent %><%= mixed_content? %>
32
- <%= namespace_and_prefix %>
33
- <%= "\#{extended_indent}map_content to: :content" if simple_content? || mixed %>
34
- <%= instances.flat_map { |instance| instance.to_xml_mapping(extended_indent) }.join -%>
35
- <%= simple_content.to_xml_mapping(extended_indent) if simple_content? -%>
36
- <%= @indent %>end
37
- <%= registration_methods -%>
38
- end
39
- <%= module_closing -%>
40
- <%= registration_execution -%>
41
- TEMPLATE
42
-
43
- def initialize(base_class: SERIALIZABLE_BASE_CLASS)
44
- @base_class = base_class
45
- @instances = []
46
- @module_namespace = nil
47
- end
48
-
49
- def <<(instance)
50
- return if instance.nil?
51
-
52
- @instances << instance
53
- end
54
-
55
- def simple_content?
56
- Utils.present?(@simple_content)
57
- end
58
-
59
- def to_class(options: {})
60
- setup_options(options)
61
- TEMPLATE.result(binding)
62
- end
63
-
64
- def required_files
65
- files = []
66
- # Only include external gem requires, not schema class requires
67
- # Schema class dependencies are handled via autoload registry
68
- unless @module_namespace
69
- files.concat(@instances.map(&:required_files).flatten.compact.uniq)
70
- files.concat(simple_content.required_files) if simple_content?
71
- end
72
- files
73
- end
74
-
75
- private
76
-
77
- def setup_options(options)
78
- namespace_uri = options[:namespace]
79
- @prefix = options[:prefix]
80
- @indent = " " * options&.fetch(:indent, 2)
81
- @extended_indent = @indent * 2
82
- @module_namespace = options[:module_namespace]
83
- @modules = @module_namespace&.split("::") || []
84
- @register_id = options[:register_id]
85
-
86
- # Get the namespace class name if namespace URI is provided
87
- if namespace_uri && XmlCompiler.namespace_classes
88
- ns_class = XmlCompiler.namespace_classes.values.find do |ns|
89
- ns.uri == namespace_uri
90
- end
91
- @namespace_class_name = ns_class&.class_name
92
- end
93
- end
94
-
95
- def module_opening
96
- return "" if @modules.empty?
97
-
98
- @modules.map.with_index do |mod, i|
99
- "#{' ' * i}module #{mod}"
100
- end.join("\n") + "\n"
101
- end
102
-
103
- def module_closing
104
- return "" if @modules.empty?
105
-
106
- @modules.reverse.map.with_index do |_mod, i|
107
- "#{' ' * (@modules.size - i - 1)}end"
108
- end.join("\n")
109
- end
110
-
111
- def registration_methods
112
- return "" if @module_namespace
113
-
114
- <<~REGISTRATION
115
-
116
- #{@indent}def self.register
117
- #{extended_indent}Lutaml::Model::Config.default_register
118
- #{@indent}end
119
-
120
- #{@indent}def self.register_class_with_id
121
- #{extended_indent}context = Lutaml::Model::GlobalContext.context(Lutaml::Model::Config.default_register)
122
- #{extended_indent}context.registry.register(:#{Utils.snake_case(name)}, self)
123
- #{@indent}end
124
- REGISTRATION
125
- end
126
-
127
- def registration_execution
128
- return "" if @module_namespace
129
-
130
- "\n#{Utils.camel_case(name)}.register_class_with_id"
131
- end
132
-
133
- def simple_content_type
134
- return "string" unless simple_content?
135
-
136
- Utils.snake_case(last_of_split(simple_content.base_class))
137
- end
138
-
139
- def simple_content_attribute
140
- SIMPLE_CONTENT_ATTRIBUTE_TEMPLATE.result(binding) if simple_content? || mixed
141
- end
142
-
143
- def mixed_content?
144
- mixed ? "mixed_content" : ""
145
- end
146
-
147
- def namespace_and_prefix
148
- return "" unless @namespace_class_name
149
-
150
- "#{@extended_indent}namespace #{@namespace_class_name}"
151
- end
152
-
153
- def extended_indent
154
- @extended_indent
155
- end
156
-
157
- def base_class_name
158
- case base_class
159
- when SERIALIZABLE_BASE_CLASS
160
- SERIALIZABLE_BASE_CLASS
161
- else
162
- Utils.camel_case(last_of_split(base_class))
163
- end
164
- end
165
-
166
- def last_of_split(field)
167
- field&.split(":")&.last
168
- end
169
- end
170
- end
171
- end
172
- end
173
- end
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lutaml
4
- module Model
5
- module Schema
6
- module XmlCompiler
7
- class Element
8
- attr_accessor :id,
9
- :ref,
10
- :name,
11
- :type,
12
- :fixed,
13
- :default,
14
- :max_occurs,
15
- :min_occurs
16
-
17
- def initialize(name: nil, ref: nil)
18
- @name = name
19
- @ref = ref
20
- end
21
-
22
- def to_attributes(indent)
23
- return if skippable?
24
- return unless resolved_type
25
-
26
- "#{indent}attribute :#{resolved_name}, :#{resolved_type}#{attribute_options}\n"
27
- end
28
-
29
- def to_xml_mapping(indent)
30
- return if skippable?
31
- return unless resolved_type
32
-
33
- "#{indent}map_element :#{resolved_name(change_case: false)}, to: :#{resolved_name}#{render_options}\n"
34
- end
35
-
36
- def required_files
37
- return if skippable?
38
-
39
- element_type = resolved_type(change_case: false)
40
- return "require \"bigdecimal\"" if element_type == "decimal"
41
- return if SimpleType.skippable?(element_type)
42
-
43
- "require_relative \"#{Utils.snake_case(element_type)}\""
44
- end
45
-
46
- private
47
-
48
- def resolved_instance
49
- @resolved_instance ||= XmlCompiler.instance_variable_get(:@elements)[last_of_split]
50
- end
51
-
52
- def resolved_type(change_case: true)
53
- @current_type ||= type || resolved_instance&.type
54
- klass_name = last_of_split(@current_type)
55
- change_case ? Utils.snake_case(klass_name) : klass_name
56
- end
57
-
58
- def resolved_name(change_case: true)
59
- @current_name ||= name || resolved_instance&.name
60
- change_case ? Utils.snake_case(@current_name) : @current_name
61
- end
62
-
63
- def collection_option
64
- return if min_occurs.nil? && max_occurs.nil?
65
-
66
- min_value = min_occurs.nil? ? 1 : min_occurs.to_i
67
- ", collection: #{min_value}..#{max_value}"
68
- end
69
-
70
- def max_value
71
- return "Float::INFINITY" if max_occurs == "unbounded"
72
- return 1 if max_occurs.nil?
73
-
74
- max_occurs.to_i
75
- end
76
-
77
- def default_option
78
- return if default.nil?
79
-
80
- ", default: -> { #{default.inspect} }"
81
- end
82
-
83
- def render_default_option
84
- return if default.nil?
85
-
86
- ", render_default: true"
87
- end
88
-
89
- def render_options
90
- options = []
91
- options << render_default_option if default
92
- options << render_empty_option if required?
93
- options.compact.join
94
- end
95
-
96
- def render_empty_option
97
- ", render_empty: true"
98
- end
99
-
100
- def required?
101
- # Element is required if minOccurs is >= 1 OR minOccurs is nil (schema default is 1)
102
- # Only NOT required if minOccurs is explicitly 0
103
- min_occurs.nil? || min_occurs.to_i >= 1
104
- end
105
-
106
- def attribute_options
107
- [collection_option, default_option].compact.join
108
- end
109
-
110
- def last_of_split(field = ref)
111
- field&.split(":")&.last
112
- end
113
-
114
- def skippable?
115
- resolved_name == "schema_location"
116
- end
117
- end
118
- end
119
- end
120
- end
121
- end
@@ -1,113 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lutaml
4
- module Model
5
- module Schema
6
- module XmlCompiler
7
- class Group
8
- attr_accessor :name, :ref, :instance
9
-
10
- GROUP_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
11
- # frozen_string_literal: true
12
-
13
- require "lutaml/model"
14
- <%= "\n" + required_files.uniq.join("\n") -%>
15
-
16
- class <%= Utils.camel_case(base_name) %> < Lutaml::Model::Serializable
17
- <%= definitions_content %>
18
- <%= xml_mapping_block -%>
19
-
20
- <%= @indent %>def self.register
21
- <%= extended_indent %>@register ||= Lutaml::Model::Config.default_register
22
- <%= @indent %>end
23
-
24
- <%= @indent %>def self.register_class_with_id
25
- <%= extended_indent %>context = Lutaml::Model::GlobalContext.context(Lutaml::Model::Config.default_register)
26
- <%= extended_indent %>context.registry.register(:<%= Utils.snake_case(base_name) %>, self)
27
- <%= @indent %>end
28
- end
29
-
30
- <%= Utils.camel_case(base_name) %>.register_class_with_id
31
- TEMPLATE
32
-
33
- XML_MAPPING_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
34
- <%= @indent %>xml do
35
- <%= extended_indent %>type_name "<%= base_name %>"
36
- <%= xml_mapping_content -%>
37
- <%= @indent %>end
38
- TEMPLATE
39
-
40
- def initialize(name = nil, ref = nil)
41
- @name = name
42
- @ref = ref
43
- end
44
-
45
- def to_xml_mapping(indent = @indent)
46
- if Utils.present?(@ref)
47
- "#{indent}import_model_mappings :#{Utils.snake_case(base_name)}\n"
48
- else
49
- @instance.to_xml_mapping(indent * 2)
50
- end
51
- end
52
-
53
- def to_class(options: {})
54
- setup_options(options)
55
- GROUP_TEMPLATE.result(binding)
56
- end
57
-
58
- def required_files
59
- if Utils.blank?(name) && Utils.present?(ref)
60
- "require_relative \"#{Utils.snake_case(ref.split(':').last)}\""
61
- else
62
- @instance&.required_files
63
- end
64
- end
65
-
66
- def to_attributes(indent = @indent)
67
- if Utils.present?(@ref)
68
- "#{indent}import_model_attributes :#{Utils.snake_case(base_name)}\n"
69
- else
70
- @instance.to_attributes(indent)
71
- end
72
- end
73
-
74
- def base_name
75
- (name || ref)&.split(":")&.last
76
- end
77
-
78
- private
79
-
80
- def setup_options(options)
81
- @indent = " " * options&.fetch(:indent, 2)
82
- end
83
-
84
- def definitions_content
85
- @definitions_content ||= instance.to_attributes(@indent)
86
- end
87
-
88
- def extended_indent
89
- @indent * 2
90
- end
91
-
92
- def xml_mapping_block
93
- XML_MAPPING_TEMPLATE.result(binding)
94
- end
95
-
96
- # Generate XML mapping content, unwrapping sequence for importable groups
97
- def xml_mapping_content
98
- return "" unless instance
99
-
100
- # For Groups (importable models without root), unwrap sequence content
101
- # because sequence requires a root element
102
- if instance.is_a?(Sequence)
103
- # Output sequence content directly without the wrapper
104
- instance.xml_block_content(extended_indent)
105
- else
106
- instance.to_xml_mapping(extended_indent)
107
- end
108
- end
109
- end
110
- end
111
- end
112
- end
113
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lutaml
4
- module Model
5
- module Schema
6
- module XmlCompiler
7
- class Restriction
8
- # transform is not a 'xsd' type, but it is used for internal purposes.
9
- attr_accessor :min_inclusive,
10
- :max_inclusive,
11
- :min_exclusive,
12
- :max_exclusive,
13
- :enumerations,
14
- :max_length,
15
- :min_length,
16
- :base_class,
17
- :pattern,
18
- :length,
19
- :transform
20
-
21
- MIN_MAX_BOUNDS = ERB.new(<<~TEMPLATE, trim_mode: "-")
22
- <%= "\#{indent}options[:max] = \#{max_inclusive || max_exclusive}" if max_bound_exist? %>
23
- <%= "\#{indent}options[:min] = \#{min_inclusive || min_exclusive}" if min_bound_exist? %>
24
- TEMPLATE
25
-
26
- PATTERN = ERB.new(<<~TEMPLATE, trim_mode: "-")
27
- <%= "\#{indent}options[:pattern] = %r{\#{pattern}}" %>
28
- TEMPLATE
29
-
30
- ENUMERATIONS = ERB.new(<<~TEMPLATE, trim_mode: "-")
31
- <%= "\#{indent}options[:values] = [\#{casted_enumerations}]" %>
32
- TEMPLATE
33
-
34
- TRANSFORM = ERB.new(<<~TEMPLATE, trim_mode: "-")
35
- <%= "\#{indent}value = \#{transform}" %>
36
- TEMPLATE
37
-
38
- def to_method_body(indent = nil)
39
- [
40
- value_for(ENUMERATIONS, type: :enumerations, indent: indent),
41
- value_for(MIN_MAX_BOUNDS, type: :min_max_bounds, indent: indent),
42
- value_for(PATTERN, type: :pattern, indent: indent),
43
- value_for(TRANSFORM, type: :transform, indent: indent),
44
- ].compact.join
45
- end
46
-
47
- def required_files
48
- if base_class_name == :decimal
49
- "require \"bigdecimal\""
50
- elsif !SimpleType::SUPPORTED_DATA_TYPES.dig(base_class_name,
51
- :skippable)
52
- "require_relative \"#{Utils.snake_case(base_class_name)}\""
53
- end
54
- end
55
-
56
- private
57
-
58
- def value_for(constant, type:, indent:)
59
- return unless send("#{type}_exist?")
60
-
61
- indent ||= " "
62
- constant.result(binding)
63
- end
64
-
65
- def min_max_bounds_exist?
66
- min_bound_exist? || max_bound_exist?
67
- end
68
-
69
- def min_bound_exist?
70
- Utils.present?(min_inclusive) || Utils.present?(min_exclusive)
71
- end
72
-
73
- def max_bound_exist?
74
- Utils.present?(max_inclusive) || Utils.present?(max_exclusive)
75
- end
76
-
77
- def pattern_exist?
78
- Utils.present?(pattern)
79
- end
80
-
81
- def enumerations_exist?
82
- Utils.present?(enumerations)
83
- end
84
-
85
- def transform_exist?
86
- Utils.present?(transform)
87
- end
88
-
89
- def base_class_name
90
- return if Utils.blank?(base_class)
91
-
92
- base_class.split(":").last.to_sym
93
- end
94
-
95
- def casted_enumerations
96
- enumerations.map do |enumeration|
97
- "super(#{enumeration.inspect})"
98
- end.join(", ")
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lutaml
4
- module Model
5
- module Schema
6
- module XmlCompiler
7
- class Sequence
8
- attr_accessor :instances
9
-
10
- XML_MAPPING_TEMPLATE = ERB.new(<<~TEMPLATE, trim_mode: "-")
11
- <%= indent %>sequence do
12
- <%= content -%>
13
- <%= indent %>end
14
- TEMPLATE
15
-
16
- def initialize
17
- @instances = []
18
- end
19
-
20
- def <<(instance)
21
- return if instance.nil?
22
-
23
- @instances << instance
24
- end
25
-
26
- def to_attributes(indent)
27
- instances.filter_map do |instance|
28
- instance.to_attributes(indent)
29
- end.join
30
- end
31
-
32
- def to_xml_mapping(indent)
33
- content = xml_block_content(indent)
34
- return "" if content.empty?
35
-
36
- XML_MAPPING_TEMPLATE.result(binding)
37
- end
38
-
39
- def required_files
40
- @instances.map(&:required_files)
41
- end
42
-
43
- def xml_block_content(indent)
44
- instances.filter_map do |instance|
45
- instance.to_xml_mapping(indent * 2)
46
- end.join
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lutaml
4
- module Model
5
- module Schema
6
- module XmlCompiler
7
- class SimpleContent
8
- attr_accessor :instances, :base_class
9
-
10
- def initialize
11
- @instances = []
12
- @base_class = nil
13
- end
14
-
15
- def <<(instance)
16
- return if instance.nil?
17
-
18
- @instances << instance
19
- end
20
-
21
- def to_attributes(indent = nil)
22
- instances.filter_map do |instance|
23
- instance.to_attributes(indent)
24
- end.join("\n")
25
- end
26
-
27
- def to_xml_mapping(indent = nil)
28
- instances.filter_map do |instance|
29
- instance.to_xml_mapping(indent)
30
- end.join("\n")
31
- end
32
-
33
- def required_files
34
- instances.flat_map(&:required_files).compact.uniq
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end