lutaml-model 0.7.1 → 0.7.7

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 (259) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.github/workflows/dependent-tests.yml +4 -0
  4. data/.github/workflows/rake.yml +12 -0
  5. data/.github/workflows/release.yml +3 -0
  6. data/.gitignore +6 -1
  7. data/.irbrc +1 -0
  8. data/.pryrc +1 -0
  9. data/.rubocop.yml +1 -1
  10. data/.rubocop_todo.yml +58 -84
  11. data/Gemfile +4 -1
  12. data/README.adoc +3115 -365
  13. data/RELEASE_NOTES.adoc +346 -0
  14. data/docs/custom_adapters.adoc +144 -0
  15. data/docs/custom_registers.adoc +228 -0
  16. data/docs/schema_generation.adoc +898 -0
  17. data/docs/schema_import.adoc +364 -0
  18. data/flake.lock +114 -0
  19. data/flake.nix +103 -0
  20. data/lib/lutaml/model/attribute.rb +242 -100
  21. data/lib/lutaml/model/choice.rb +30 -0
  22. data/lib/lutaml/model/collection.rb +212 -0
  23. data/lib/lutaml/model/comparable_model.rb +3 -3
  24. data/lib/lutaml/model/config.rb +71 -42
  25. data/lib/lutaml/model/constants.rb +2 -0
  26. data/lib/lutaml/model/error/element_count_out_of_range_error.rb +29 -0
  27. data/lib/lutaml/model/error/invalid_attribute_name_error.rb +15 -0
  28. data/lib/lutaml/model/error/invalid_attribute_options_error.rb +16 -0
  29. data/lib/lutaml/model/error/invalid_choice_range_error.rb +3 -5
  30. data/lib/lutaml/model/error/polymorphic_error.rb +7 -2
  31. data/lib/lutaml/model/error/register/not_registrable_class_error.rb +11 -0
  32. data/lib/lutaml/model/error/type/invalid_value_error.rb +5 -3
  33. data/lib/lutaml/model/error/type/max_bound_error.rb +20 -0
  34. data/lib/lutaml/model/error/type/max_length_error.rb +20 -0
  35. data/lib/lutaml/model/error/type/min_bound_error.rb +20 -0
  36. data/lib/lutaml/model/error/type/min_length_error.rb +20 -0
  37. data/lib/lutaml/model/error/type/pattern_not_matched_error.rb +18 -0
  38. data/lib/lutaml/model/error/validation_failed_error.rb +9 -0
  39. data/lib/lutaml/model/error.rb +10 -0
  40. data/lib/lutaml/model/errors.rb +36 -0
  41. data/lib/lutaml/model/format_registry.rb +44 -0
  42. data/lib/lutaml/model/global_register.rb +41 -0
  43. data/lib/lutaml/model/hash_adapter/document.rb +11 -0
  44. data/lib/lutaml/model/hash_adapter/mapping.rb +19 -0
  45. data/lib/lutaml/model/hash_adapter/mapping_rule.rb +9 -0
  46. data/lib/lutaml/model/hash_adapter/standard_adapter.rb +17 -0
  47. data/lib/lutaml/model/hash_adapter/transform.rb +8 -0
  48. data/lib/lutaml/model/hash_adapter.rb +21 -0
  49. data/lib/lutaml/model/json/document.rb +11 -0
  50. data/lib/lutaml/model/json/mapping.rb +19 -0
  51. data/lib/lutaml/model/json/mapping_rule.rb +9 -0
  52. data/lib/lutaml/model/{json_adapter → json}/multi_json_adapter.rb +4 -5
  53. data/lib/lutaml/model/{json_adapter/standard_json_adapter.rb → json/standard_adapter.rb} +5 -3
  54. data/lib/lutaml/model/json/transform.rb +8 -0
  55. data/lib/lutaml/model/json.rb +21 -0
  56. data/lib/lutaml/model/jsonl/document.rb +14 -0
  57. data/lib/lutaml/model/jsonl/mapping.rb +19 -0
  58. data/lib/lutaml/model/jsonl/mapping_rule.rb +9 -0
  59. data/lib/lutaml/model/jsonl/standard_adapter.rb +33 -0
  60. data/lib/lutaml/model/jsonl/transform.rb +19 -0
  61. data/lib/lutaml/model/jsonl.rb +21 -0
  62. data/lib/lutaml/model/key_value_document.rb +28 -0
  63. data/lib/lutaml/model/mapping/key_value_mapping.rb +85 -13
  64. data/lib/lutaml/model/mapping/key_value_mapping_rule.rb +5 -0
  65. data/lib/lutaml/model/mapping/mapping.rb +13 -0
  66. data/lib/lutaml/model/mapping/mapping_rule.rb +15 -9
  67. data/lib/lutaml/model/register.rb +105 -0
  68. data/lib/lutaml/model/{toml_adapter.rb → registrable.rb} +1 -1
  69. data/lib/lutaml/model/schema/base_schema.rb +64 -0
  70. data/lib/lutaml/model/schema/decorators/attribute.rb +114 -0
  71. data/lib/lutaml/model/schema/decorators/choices.rb +31 -0
  72. data/lib/lutaml/model/schema/decorators/class_definition.rb +85 -0
  73. data/lib/lutaml/model/schema/decorators/definition_collection.rb +97 -0
  74. data/lib/lutaml/model/schema/generator/definition.rb +53 -0
  75. data/lib/lutaml/model/schema/generator/definitions_collection.rb +81 -0
  76. data/lib/lutaml/model/schema/generator/properties_collection.rb +63 -0
  77. data/lib/lutaml/model/schema/generator/property.rb +110 -0
  78. data/lib/lutaml/model/schema/generator/ref.rb +24 -0
  79. data/lib/lutaml/model/schema/helpers/template_helper.rb +49 -0
  80. data/lib/lutaml/model/schema/json_schema.rb +42 -49
  81. data/lib/lutaml/model/schema/relaxng_schema.rb +14 -10
  82. data/lib/lutaml/model/schema/renderer.rb +36 -0
  83. data/lib/lutaml/model/schema/shared_methods.rb +24 -0
  84. data/lib/lutaml/model/schema/templates/model.erb +9 -0
  85. data/lib/lutaml/model/schema/xml_compiler/attribute.rb +85 -0
  86. data/lib/lutaml/model/schema/xml_compiler/attribute_group.rb +45 -0
  87. data/lib/lutaml/model/schema/xml_compiler/choice.rb +65 -0
  88. data/lib/lutaml/model/schema/xml_compiler/complex_content.rb +27 -0
  89. data/lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb +34 -0
  90. data/lib/lutaml/model/schema/xml_compiler/complex_type.rb +136 -0
  91. data/lib/lutaml/model/schema/xml_compiler/element.rb +104 -0
  92. data/lib/lutaml/model/schema/xml_compiler/group.rb +97 -0
  93. data/lib/lutaml/model/schema/xml_compiler/restriction.rb +101 -0
  94. data/lib/lutaml/model/schema/xml_compiler/sequence.rb +50 -0
  95. data/lib/lutaml/model/schema/xml_compiler/simple_content.rb +36 -0
  96. data/lib/lutaml/model/schema/xml_compiler/simple_type.rb +189 -0
  97. data/lib/lutaml/model/schema/xml_compiler.rb +231 -587
  98. data/lib/lutaml/model/schema/xsd_schema.rb +12 -8
  99. data/lib/lutaml/model/schema/yaml_schema.rb +41 -35
  100. data/lib/lutaml/model/schema.rb +1 -0
  101. data/lib/lutaml/model/sequence.rb +60 -30
  102. data/lib/lutaml/model/serialization_adapter.rb +22 -0
  103. data/lib/lutaml/model/serialize.rb +296 -548
  104. data/lib/lutaml/model/services/base.rb +11 -0
  105. data/lib/lutaml/model/services/logger.rb +54 -0
  106. data/lib/lutaml/model/services/rule_value_extractor.rb +92 -0
  107. data/lib/lutaml/model/services/transformer.rb +48 -0
  108. data/lib/lutaml/model/services/type/validator/number.rb +25 -0
  109. data/lib/lutaml/model/services/type/validator/string.rb +52 -0
  110. data/lib/lutaml/model/services/type/validator.rb +43 -0
  111. data/lib/lutaml/model/services/validator.rb +145 -0
  112. data/lib/lutaml/model/services.rb +5 -0
  113. data/lib/lutaml/model/toml/document.rb +11 -0
  114. data/lib/lutaml/model/toml/mapping.rb +27 -0
  115. data/lib/lutaml/model/toml/mapping_rule.rb +9 -0
  116. data/lib/lutaml/model/{toml_adapter → toml}/toml_rb_adapter.rb +3 -3
  117. data/lib/lutaml/model/toml/tomlib_adapter.rb +19 -0
  118. data/lib/lutaml/model/toml/transform.rb +8 -0
  119. data/lib/lutaml/model/toml.rb +30 -0
  120. data/lib/lutaml/model/transform/key_value_transform.rb +297 -0
  121. data/lib/lutaml/model/transform/xml_transform.rb +228 -0
  122. data/lib/lutaml/model/transform.rb +93 -0
  123. data/lib/lutaml/model/type/boolean.rb +1 -1
  124. data/lib/lutaml/model/type/date.rb +1 -1
  125. data/lib/lutaml/model/type/date_time.rb +1 -1
  126. data/lib/lutaml/model/type/decimal.rb +11 -9
  127. data/lib/lutaml/model/type/float.rb +2 -1
  128. data/lib/lutaml/model/type/integer.rb +24 -21
  129. data/lib/lutaml/model/type/string.rb +4 -2
  130. data/lib/lutaml/model/type/time.rb +1 -1
  131. data/lib/lutaml/model/type/time_without_date.rb +1 -1
  132. data/lib/lutaml/model/type/value.rb +11 -10
  133. data/lib/lutaml/model/type.rb +5 -2
  134. data/lib/lutaml/model/uninitialized_class.rb +1 -1
  135. data/lib/lutaml/model/utils.rb +56 -4
  136. data/lib/lutaml/model/validation.rb +6 -4
  137. data/lib/lutaml/model/version.rb +1 -1
  138. data/lib/lutaml/model/{xml_adapter → xml}/builder/nokogiri.rb +2 -2
  139. data/lib/lutaml/model/{xml_adapter → xml}/builder/oga.rb +10 -10
  140. data/lib/lutaml/model/{xml_adapter → xml}/builder/ox.rb +1 -1
  141. data/lib/lutaml/model/{xml_adapter/xml_document.rb → xml/document.rb} +42 -25
  142. data/lib/lutaml/model/xml/element.rb +32 -0
  143. data/lib/lutaml/model/xml/mapping.rb +471 -0
  144. data/lib/lutaml/model/xml/mapping_rule.rb +149 -0
  145. data/lib/lutaml/model/xml/nokogiri_adapter.rb +234 -0
  146. data/lib/lutaml/model/{xml_adapter → xml}/oga/document.rb +1 -1
  147. data/lib/lutaml/model/{xml_adapter → xml}/oga/element.rb +7 -2
  148. data/lib/lutaml/model/xml/oga_adapter.rb +172 -0
  149. data/lib/lutaml/model/xml/ox_adapter.rb +229 -0
  150. data/lib/lutaml/model/xml/transform.rb +8 -0
  151. data/lib/lutaml/model/{xml_adapter → xml}/xml_attribute.rb +1 -1
  152. data/lib/lutaml/model/{xml_adapter → xml}/xml_element.rb +9 -31
  153. data/lib/lutaml/model/{xml_adapter → xml}/xml_namespace.rb +1 -1
  154. data/lib/lutaml/model/xml.rb +31 -0
  155. data/lib/lutaml/model/xml_adapter/element.rb +11 -25
  156. data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +6 -223
  157. data/lib/lutaml/model/xml_adapter/oga_adapter.rb +13 -163
  158. data/lib/lutaml/model/xml_adapter/ox_adapter.rb +10 -207
  159. data/lib/lutaml/model/yaml/document.rb +10 -0
  160. data/lib/lutaml/model/yaml/mapping.rb +19 -0
  161. data/lib/lutaml/model/yaml/mapping_rule.rb +9 -0
  162. data/lib/lutaml/model/{yaml_adapter/standard_yaml_adapter.rb → yaml/standard_adapter.rb} +4 -3
  163. data/lib/lutaml/model/yaml/transform.rb +8 -0
  164. data/lib/lutaml/model/yaml.rb +21 -0
  165. data/lib/lutaml/model/yamls/document.rb +14 -0
  166. data/lib/lutaml/model/yamls/mapping.rb +19 -0
  167. data/lib/lutaml/model/yamls/mapping_rule.rb +9 -0
  168. data/lib/lutaml/model/yamls/standard_adapter.rb +34 -0
  169. data/lib/lutaml/model/yamls/transform.rb +19 -0
  170. data/lib/lutaml/model/yamls.rb +21 -0
  171. data/lib/lutaml/model.rb +15 -4
  172. data/lutaml-model.gemspec +0 -4
  173. data/spec/benchmarks/xml_parsing_benchmark_spec.rb +5 -6
  174. data/spec/fixtures/xml/advanced_test_schema.xsd +134 -0
  175. data/spec/fixtures/xml/examples/nested_categories.xml +55 -0
  176. data/spec/fixtures/xml/examples/valid_catalog.xml +43 -0
  177. data/spec/fixtures/xml/product_catalog.xsd +151 -0
  178. data/spec/fixtures/xml/specifications_schema.xsd +38 -0
  179. data/spec/lutaml/model/attribute_collection_spec.rb +101 -0
  180. data/spec/lutaml/model/attribute_spec.rb +41 -44
  181. data/spec/lutaml/model/cdata_spec.rb +7 -7
  182. data/spec/lutaml/model/choice_spec.rb +44 -0
  183. data/spec/lutaml/model/custom_bibtex_adapter_spec.rb +598 -0
  184. data/spec/lutaml/model/custom_collection_spec.rb +830 -0
  185. data/spec/lutaml/model/custom_vobject_adapter_spec.rb +1226 -0
  186. data/spec/lutaml/model/global_register_spec.rb +108 -0
  187. data/spec/lutaml/model/group_spec.rb +27 -10
  188. data/spec/lutaml/model/hash/adapter_spec.rb +255 -0
  189. data/spec/lutaml/model/json_adapter_spec.rb +6 -6
  190. data/spec/lutaml/model/jsonl/standard_adapter_spec.rb +91 -0
  191. data/spec/lutaml/model/jsonl_spec.rb +229 -0
  192. data/spec/lutaml/model/key_value_mapping_spec.rb +25 -1
  193. data/spec/lutaml/model/mixed_content_spec.rb +24 -24
  194. data/spec/lutaml/model/multiple_mapping_spec.rb +6 -6
  195. data/spec/lutaml/model/ordered_content_spec.rb +6 -6
  196. data/spec/lutaml/model/polymorphic_spec.rb +178 -0
  197. data/spec/lutaml/model/register/key_value_spec.rb +275 -0
  198. data/spec/lutaml/model/register/xml_spec.rb +185 -0
  199. data/spec/lutaml/model/register_spec.rb +147 -0
  200. data/spec/lutaml/model/root_mappings_spec.rb +3 -3
  201. data/spec/lutaml/model/rule_value_extractor_spec.rb +162 -0
  202. data/spec/lutaml/model/schema/generator/definitions_collection_spec.rb +120 -0
  203. data/spec/lutaml/model/schema/json_schema_spec.rb +412 -51
  204. data/spec/lutaml/model/schema/json_schema_to_models_spec.rb +383 -0
  205. data/spec/lutaml/model/schema/xml_compiler/attribute_group_spec.rb +65 -0
  206. data/spec/lutaml/model/schema/xml_compiler/attribute_spec.rb +63 -0
  207. data/spec/lutaml/model/schema/xml_compiler/choice_spec.rb +71 -0
  208. data/spec/lutaml/model/schema/xml_compiler/complex_content_restriction_spec.rb +55 -0
  209. data/spec/lutaml/model/schema/xml_compiler/complex_content_spec.rb +37 -0
  210. data/spec/lutaml/model/schema/xml_compiler/complex_type_spec.rb +173 -0
  211. data/spec/lutaml/model/schema/xml_compiler/element_spec.rb +63 -0
  212. data/spec/lutaml/model/schema/xml_compiler/group_spec.rb +86 -0
  213. data/spec/lutaml/model/schema/xml_compiler/restriction_spec.rb +76 -0
  214. data/spec/lutaml/model/schema/xml_compiler/sequence_spec.rb +59 -0
  215. data/spec/lutaml/model/schema/xml_compiler/simple_content_spec.rb +55 -0
  216. data/spec/lutaml/model/schema/xml_compiler/simple_type_spec.rb +181 -0
  217. data/spec/lutaml/model/schema/xml_compiler_spec.rb +503 -1804
  218. data/spec/lutaml/model/schema/yaml_schema_spec.rb +249 -26
  219. data/spec/lutaml/model/sequence_spec.rb +36 -0
  220. data/spec/lutaml/model/serializable_spec.rb +201 -94
  221. data/spec/lutaml/model/toml_adapter_spec.rb +6 -6
  222. data/spec/lutaml/model/toml_spec.rb +51 -0
  223. data/spec/lutaml/model/transformation_spec.rb +72 -15
  224. data/spec/lutaml/model/type_spec.rb +8 -4
  225. data/spec/lutaml/model/uninitialized_class_spec.rb +96 -0
  226. data/spec/lutaml/model/utils_spec.rb +3 -3
  227. data/spec/lutaml/model/xml/derived_attributes_spec.rb +1 -1
  228. data/spec/lutaml/model/xml/namespace_spec.rb +57 -0
  229. data/spec/lutaml/model/xml/root_mappings/nested_child_mappings_spec.rb +217 -0
  230. data/spec/lutaml/model/xml/xml_element_spec.rb +7 -1
  231. data/spec/lutaml/model/xml_adapter/nokogiri_adapter_spec.rb +2 -2
  232. data/spec/lutaml/model/xml_adapter/oga_adapter_spec.rb +2 -2
  233. data/spec/lutaml/model/xml_adapter/ox_adapter_spec.rb +2 -2
  234. data/spec/lutaml/model/xml_adapter/xml_namespace_spec.rb +12 -12
  235. data/spec/lutaml/model/xml_adapter_spec.rb +30 -6
  236. data/spec/lutaml/model/xml_mapping_rule_spec.rb +14 -7
  237. data/spec/lutaml/model/xml_mapping_spec.rb +27 -15
  238. data/spec/lutaml/model/xml_spec.rb +63 -0
  239. data/spec/lutaml/model/yaml_adapter_spec.rb +3 -5
  240. data/spec/lutaml/model/yamls/standard_adapter_spec.rb +183 -0
  241. data/spec/lutaml/model/yamls_spec.rb +294 -0
  242. data/spec/spec_helper.rb +4 -3
  243. metadata +162 -60
  244. data/lib/lutaml/model/json_adapter/json_document.rb +0 -20
  245. data/lib/lutaml/model/json_adapter/json_object.rb +0 -28
  246. data/lib/lutaml/model/loggable.rb +0 -15
  247. data/lib/lutaml/model/mapping/json_mapping.rb +0 -17
  248. data/lib/lutaml/model/mapping/toml_mapping.rb +0 -25
  249. data/lib/lutaml/model/mapping/xml_mapping.rb +0 -389
  250. data/lib/lutaml/model/mapping/xml_mapping_rule.rb +0 -139
  251. data/lib/lutaml/model/mapping/yaml_mapping.rb +0 -17
  252. data/lib/lutaml/model/mapping.rb +0 -14
  253. data/lib/lutaml/model/schema/templates/simple_type.rb +0 -247
  254. data/lib/lutaml/model/toml_adapter/toml_document.rb +0 -20
  255. data/lib/lutaml/model/toml_adapter/toml_object.rb +0 -28
  256. data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +0 -20
  257. data/lib/lutaml/model/yaml_adapter/yaml_document.rb +0 -20
  258. data/lib/lutaml/model/yaml_adapter/yaml_object.rb +0 -28
  259. data/lib/lutaml/model/yaml_adapter.rb +0 -8
@@ -0,0 +1,471 @@
1
+ require_relative "../mapping/mapping"
2
+ require_relative "mapping_rule"
3
+
4
+ module Lutaml
5
+ module Model
6
+ module Xml
7
+ class Mapping < Mapping
8
+ TYPES = {
9
+ attribute: :map_attribute,
10
+ element: :map_element,
11
+ content: :map_content,
12
+ all_content: :map_all,
13
+ }.freeze
14
+
15
+ attr_reader :root_element,
16
+ :namespace_uri,
17
+ :namespace_prefix,
18
+ :mixed_content,
19
+ :ordered,
20
+ :element_sequence,
21
+ :mappings_imported
22
+
23
+ def initialize
24
+ super
25
+
26
+ @elements = {}
27
+ @attributes = {}
28
+ @element_sequence = []
29
+ @content_mapping = nil
30
+ @raw_mapping = nil
31
+ @mixed_content = false
32
+ @format = :xml
33
+ @mappings_imported = true
34
+ @finalized = false
35
+ end
36
+
37
+ def finalize(mapper_class)
38
+ if !root_element && !no_root?
39
+ root(mapper_class.model.to_s)
40
+ end
41
+ @finalized = true
42
+ end
43
+
44
+ def finalized?
45
+ @finalized
46
+ end
47
+
48
+ alias mixed_content? mixed_content
49
+ alias ordered? ordered
50
+
51
+ def root(name, mixed: false, ordered: false)
52
+ @root_element = name
53
+ @mixed_content = mixed
54
+ @ordered = ordered || mixed # mixed contenet will always be ordered
55
+ end
56
+
57
+ def root?
58
+ !!root_element
59
+ end
60
+
61
+ def no_root
62
+ @no_root = true
63
+ end
64
+
65
+ def no_root?
66
+ !!@no_root
67
+ end
68
+
69
+ def prefixed_root
70
+ if namespace_uri && namespace_prefix
71
+ "#{namespace_prefix}:#{root_element}"
72
+ else
73
+ root_element
74
+ end
75
+ end
76
+
77
+ def namespace(uri, prefix = nil)
78
+ raise Lutaml::Model::NoRootNamespaceError if no_root?
79
+
80
+ @namespace_uri = uri
81
+ @namespace_prefix = prefix
82
+ end
83
+
84
+ def map_instances(to:)
85
+ map_element(to, to: to)
86
+ end
87
+
88
+ # rubocop:disable Metrics/ParameterLists
89
+ def map_element(
90
+ name,
91
+ to: nil,
92
+ render_nil: false,
93
+ render_default: false,
94
+ render_empty: false,
95
+ treat_nil: :nil,
96
+ treat_empty: :empty,
97
+ treat_omitted: :nil,
98
+ with: {},
99
+ delegate: nil,
100
+ cdata: false,
101
+ polymorphic: {},
102
+ namespace: (namespace_set = false
103
+ nil),
104
+ prefix: (prefix_set = false
105
+ nil),
106
+ transform: {},
107
+ value_map: {}
108
+ )
109
+ validate!(
110
+ name, to, with, render_nil, render_empty, type: TYPES[:element]
111
+ )
112
+
113
+ rule = MappingRule.new(
114
+ name,
115
+ to: to,
116
+ render_nil: render_nil,
117
+ render_default: render_default,
118
+ render_empty: render_empty,
119
+ treat_nil: treat_nil,
120
+ treat_empty: treat_empty,
121
+ treat_omitted: treat_omitted,
122
+ with: with,
123
+ delegate: delegate,
124
+ cdata: cdata,
125
+ namespace: namespace,
126
+ default_namespace: namespace_uri,
127
+ prefix: prefix,
128
+ polymorphic: polymorphic,
129
+ namespace_set: namespace_set != false,
130
+ prefix_set: prefix_set != false,
131
+ transform: transform,
132
+ value_map: value_map,
133
+ )
134
+ @elements[rule.namespaced_name] = rule
135
+ end
136
+
137
+ def map_attribute(
138
+ name,
139
+ to: nil,
140
+ render_nil: false,
141
+ render_default: false,
142
+ render_empty: false,
143
+ with: {},
144
+ delegate: nil,
145
+ polymorphic_map: {},
146
+ namespace: (namespace_set = false
147
+ nil),
148
+ prefix: (prefix_set = false
149
+ nil),
150
+ transform: {},
151
+ value_map: {}
152
+ )
153
+ validate!(
154
+ name, to, with, render_nil, render_empty, type: TYPES[:attribute]
155
+ )
156
+
157
+ if name == "schemaLocation"
158
+ Logger.warn_auto_handling(
159
+ name: name,
160
+ caller_file: File.basename(caller_locations(1, 1)[0].path),
161
+ caller_line: caller_locations(1, 1)[0].lineno,
162
+ )
163
+ end
164
+
165
+ rule = MappingRule.new(
166
+ name,
167
+ to: to,
168
+ render_nil: render_nil,
169
+ render_default: render_default,
170
+ with: with,
171
+ delegate: delegate,
172
+ namespace: namespace,
173
+ prefix: prefix,
174
+ attribute: true,
175
+ polymorphic_map: polymorphic_map,
176
+ default_namespace: namespace_uri,
177
+ namespace_set: namespace_set != false,
178
+ prefix_set: prefix_set != false,
179
+ transform: transform,
180
+ value_map: value_map,
181
+ )
182
+ @attributes[rule.namespaced_name] = rule
183
+ end
184
+
185
+ # rubocop:enable Metrics/ParameterLists
186
+
187
+ def map_content(
188
+ to: nil,
189
+ render_nil: false,
190
+ render_default: false,
191
+ render_empty: false,
192
+ with: {},
193
+ delegate: nil,
194
+ mixed: false,
195
+ cdata: false,
196
+ transform: {},
197
+ value_map: {}
198
+ )
199
+ validate!(
200
+ "content", to, with, render_nil, render_empty, type: TYPES[:content]
201
+ )
202
+
203
+ @content_mapping = MappingRule.new(
204
+ nil,
205
+ to: to,
206
+ render_nil: render_nil,
207
+ render_default: render_default,
208
+ render_empty: render_empty,
209
+ with: with,
210
+ delegate: delegate,
211
+ mixed_content: mixed,
212
+ cdata: cdata,
213
+ transform: transform,
214
+ value_map: value_map,
215
+ )
216
+ end
217
+
218
+ def map_all(
219
+ to:,
220
+ render_nil: false,
221
+ render_default: false,
222
+ delegate: nil,
223
+ with: {},
224
+ namespace: (namespace_set = false
225
+ nil),
226
+ prefix: (prefix_set = false
227
+ nil),
228
+ render_empty: false
229
+ )
230
+ validate!(
231
+ Constants::RAW_MAPPING_KEY,
232
+ to,
233
+ with,
234
+ render_nil,
235
+ render_empty,
236
+ type: TYPES[:all_content],
237
+ )
238
+
239
+ rule = MappingRule.new(
240
+ Constants::RAW_MAPPING_KEY,
241
+ to: to,
242
+ render_nil: render_nil,
243
+ render_default: render_default,
244
+ with: with,
245
+ delegate: delegate,
246
+ namespace: namespace,
247
+ prefix: prefix,
248
+ default_namespace: namespace_uri,
249
+ namespace_set: namespace_set != false,
250
+ prefix_set: prefix_set != false,
251
+ )
252
+
253
+ @raw_mapping = rule
254
+ end
255
+
256
+ alias map_all_content map_all
257
+
258
+ def sequence(&block)
259
+ @element_sequence << Sequence.new(self).tap { |s| s.instance_eval(&block) }
260
+ end
261
+
262
+ def import_model_mappings(model)
263
+ return import_mappings_later(model) if model_importable?(model)
264
+ raise Lutaml::Model::ImportModelWithRootError.new(model) if model.root?
265
+
266
+ mappings = model.mappings_for(:xml)
267
+ @elements.merge!(mappings.instance_variable_get(:@elements))
268
+ @attributes.merge!(mappings.instance_variable_get(:@attributes))
269
+ (@element_sequence << mappings.element_sequence).flatten!
270
+ end
271
+
272
+ def set_mappings_imported(value)
273
+ @mappings_imported = value
274
+ end
275
+
276
+ def validate!(key, to, with, render_nil, render_empty, type: nil)
277
+ validate_raw_mappings!(type)
278
+ validate_to_and_with_arguments!(key, to, with)
279
+
280
+ if render_nil == :as_empty || render_empty == :as_empty
281
+ raise IncorrectMappingArgumentsError.new(
282
+ ":as_empty is not supported for XML mappings",
283
+ )
284
+ end
285
+ end
286
+
287
+ def validate_to_and_with_arguments!(key, to, with)
288
+ if to.nil? && with.empty?
289
+ raise IncorrectMappingArgumentsError.new(
290
+ ":to or :with argument is required for mapping '#{key}'",
291
+ )
292
+ end
293
+
294
+ validate_with_options!(key, to, with)
295
+ end
296
+
297
+ def validate_with_options!(key, to, with)
298
+ return true if to
299
+
300
+ if !with.empty? && (with[:from].nil? || with[:to].nil?)
301
+ raise IncorrectMappingArgumentsError.new(
302
+ ":with argument for mapping '#{key}' requires :to and :from keys",
303
+ )
304
+ end
305
+ end
306
+
307
+ def validate_raw_mappings!(type)
308
+ if !@raw_mapping.nil? && type != TYPES[:attribute]
309
+ raise StandardError, "#{type} is not allowed, only #{TYPES[:attribute]} " \
310
+ "is allowed with #{TYPES[:all_content]}"
311
+ end
312
+
313
+ if !(elements.empty? && content_mapping.nil?) && type == TYPES[:all_content]
314
+ raise StandardError, "#{TYPES[:all_content]} is not allowed with other mappings"
315
+ end
316
+ end
317
+
318
+ def elements
319
+ @elements.values
320
+ end
321
+
322
+ def attributes
323
+ @attributes.values
324
+ end
325
+
326
+ def content_mapping
327
+ @content_mapping
328
+ end
329
+
330
+ def raw_mapping
331
+ @raw_mapping
332
+ end
333
+
334
+ def mappings(register_id = nil)
335
+ ensure_mappings_imported!(register_id) if finalized?
336
+ elements + attributes + [content_mapping, raw_mapping].compact
337
+ end
338
+
339
+ def ensure_mappings_imported!(register_id = nil)
340
+ return if @mappings_imported
341
+
342
+ importable_mappings.each do |model|
343
+ import_model_mappings(
344
+ register(register_id).get_class_without_register(model),
345
+ )
346
+ end
347
+
348
+ sequence_importable_mappings.each do |sequence, models|
349
+ models.each do |model|
350
+ sequence.import_model_mappings(
351
+ register(register_id).get_class_without_register(model),
352
+ )
353
+ end
354
+ end
355
+
356
+ @mappings_imported = true
357
+ end
358
+
359
+ def importable_mappings
360
+ @importable_mappings ||= []
361
+ end
362
+
363
+ def sequence_importable_mappings
364
+ @sequence_importable_mappings ||= Hash.new { |h, k| h[k] = [] }
365
+ end
366
+
367
+ def element(name)
368
+ elements.detect { |rule| name == rule.to }
369
+ end
370
+
371
+ def attribute(name)
372
+ attributes.detect { |rule| name == rule.to }
373
+ end
374
+
375
+ def find_by_name(name, type: "Text")
376
+ if ["text", "#cdata-section"].include?(name.to_s) && type == "Text"
377
+ content_mapping
378
+ else
379
+ mappings.detect do |rule|
380
+ rule.name == name.to_s || rule.name == name.to_sym
381
+ end
382
+ end
383
+ end
384
+
385
+ def find_by_to(to)
386
+ mappings.detect { |rule| rule.to.to_s == to.to_s }
387
+ end
388
+
389
+ def mapping_attributes_hash
390
+ @attributes
391
+ end
392
+
393
+ def mapping_elements_hash
394
+ @elements
395
+ end
396
+
397
+ def merge_mapping_attributes(mapping)
398
+ mapping_attributes_hash.merge!(mapping.mapping_attributes_hash)
399
+ end
400
+
401
+ def merge_mapping_elements(mapping)
402
+ mapping_elements_hash.merge!(mapping.mapping_elements_hash)
403
+ end
404
+
405
+ def merge_elements_sequence(mapping)
406
+ mapping.element_sequence.each do |sequence|
407
+ element_sequence << Lutaml::Model::Sequence.new(self).tap do |instance|
408
+ sequence.attributes.each do |attr|
409
+ instance.attributes << attr.deep_dup
410
+ end
411
+ end
412
+ end
413
+ end
414
+
415
+ def deep_dup
416
+ self.class.new.tap do |xml_mapping|
417
+ xml_mapping.root(@root_element.dup, mixed: @mixed_content,
418
+ ordered: @ordered)
419
+ xml_mapping.namespace(@namespace_uri.dup, @namespace_prefix.dup)
420
+
421
+ attributes_to_dup.each do |var_name|
422
+ value = instance_variable_get(var_name)
423
+ xml_mapping.instance_variable_set(var_name, Utils.deep_dup(value))
424
+ end
425
+ xml_mapping.instance_variable_set(:@finalized, true)
426
+ end
427
+ end
428
+
429
+ def polymorphic_mapping
430
+ mappings.find(&:polymorphic_mapping?)
431
+ end
432
+
433
+ def attributes_to_dup
434
+ @attributes_to_dup ||= %i[
435
+ @content_mapping
436
+ @raw_mapping
437
+ @element_sequence
438
+ @attributes
439
+ @elements
440
+ ]
441
+ end
442
+
443
+ def dup_mappings(mappings)
444
+ new_mappings = {}
445
+
446
+ mappings.each do |key, mapping_rule|
447
+ new_mappings[key] = mapping_rule.deep_dup
448
+ end
449
+
450
+ new_mappings
451
+ end
452
+
453
+ private
454
+
455
+ def register(register_id = nil)
456
+ register_id ||= Lutaml::Model::Config.default_register
457
+ Lutaml::Model::GlobalRegister.lookup(register_id)
458
+ end
459
+
460
+ def model_importable?(model)
461
+ model.is_a?(Symbol) || model.is_a?(String)
462
+ end
463
+
464
+ def import_mappings_later(model)
465
+ importable_mappings << model.to_sym
466
+ @mappings_imported = false
467
+ end
468
+ end
469
+ end
470
+ end
471
+ end
@@ -0,0 +1,149 @@
1
+ require_relative "../mapping/mapping_rule"
2
+
3
+ module Lutaml
4
+ module Model
5
+ module Xml
6
+ class MappingRule < MappingRule
7
+ attr_reader :namespace,
8
+ :prefix,
9
+ :mixed_content,
10
+ :default_namespace,
11
+ :cdata
12
+
13
+ def initialize(
14
+ name,
15
+ to:,
16
+ render_nil: false,
17
+ render_default: false,
18
+ render_empty: false,
19
+ treat_nil: nil,
20
+ treat_empty: nil,
21
+ treat_omitted: nil,
22
+ with: {},
23
+ delegate: nil,
24
+ namespace: nil,
25
+ prefix: nil,
26
+ mixed_content: false,
27
+ cdata: false,
28
+ namespace_set: false,
29
+ prefix_set: false,
30
+ attribute: false,
31
+ default_namespace: nil,
32
+ polymorphic: {},
33
+ polymorphic_map: {},
34
+ transform: {},
35
+ value_map: {}
36
+ )
37
+ super(
38
+ name,
39
+ to: to,
40
+ render_nil: render_nil,
41
+ render_default: render_default,
42
+ render_empty: render_empty,
43
+ treat_nil: treat_nil,
44
+ treat_empty: treat_empty,
45
+ treat_omitted: treat_omitted,
46
+ with: with,
47
+ delegate: delegate,
48
+ attribute: attribute,
49
+ polymorphic: polymorphic,
50
+ polymorphic_map: polymorphic_map,
51
+ transform: transform,
52
+ value_map: value_map,
53
+ )
54
+
55
+ @namespace = if namespace.to_s == "inherit"
56
+ # we are using inherit_namespace in xml builder by
57
+ # default so no need to do anything here.
58
+ else
59
+ namespace
60
+ end
61
+ @prefix = prefix
62
+ @mixed_content = mixed_content
63
+ @cdata = cdata
64
+
65
+ @default_namespace = default_namespace
66
+
67
+ @namespace_set = namespace_set
68
+ @prefix_set = prefix_set
69
+ end
70
+
71
+ def namespace_set?
72
+ !!@namespace_set
73
+ end
74
+
75
+ def prefix_set?
76
+ !!@prefix_set
77
+ end
78
+
79
+ def content_mapping?
80
+ name.nil?
81
+ end
82
+
83
+ def content_key
84
+ cdata ? "#cdata-section" : "text"
85
+ end
86
+
87
+ def castable?
88
+ !raw_mapping? && !content_mapping? && !custom_methods[:from]
89
+ end
90
+
91
+ def mixed_content?
92
+ !!@mixed_content
93
+ end
94
+
95
+ def prefixed_name
96
+ rule_name = multiple_mappings? ? name.first : name
97
+ if prefix
98
+ "#{prefix}:#{rule_name}"
99
+ else
100
+ rule_name
101
+ end
102
+ end
103
+
104
+ def namespaced_names(parent_namespace = nil)
105
+ if multiple_mappings?
106
+ name.map { |rule_name| namespaced_name(parent_namespace, rule_name) }
107
+ else
108
+ [namespaced_name(parent_namespace)]
109
+ end
110
+ end
111
+
112
+ def namespaced_name(parent_namespace = nil, name = self.name)
113
+ if name.to_s == "lang"
114
+ Utils.blank?(prefix) ? name.to_s : "#{prefix}:#{name}"
115
+ elsif namespace_set? || @attribute
116
+ [namespace, name].compact.join(":")
117
+ elsif default_namespace
118
+ "#{default_namespace}:#{name}"
119
+ else
120
+ [parent_namespace, name].compact.join(":")
121
+ end
122
+ end
123
+
124
+ def deep_dup
125
+ self.class.new(
126
+ name.dup,
127
+ to: to,
128
+ render_nil: render_nil,
129
+ render_default: render_default,
130
+ with: Utils.deep_dup(custom_methods),
131
+ delegate: delegate,
132
+ namespace: namespace.dup,
133
+ prefix: prefix.dup,
134
+ mixed_content: mixed_content,
135
+ cdata: cdata,
136
+ namespace_set: namespace_set?,
137
+ prefix_set: prefix_set?,
138
+ attribute: attribute,
139
+ polymorphic: polymorphic.dup,
140
+ default_namespace: default_namespace.dup,
141
+ transform: transform.dup,
142
+ render_empty: render_empty.dup,
143
+ value_map: Utils.deep_dup(@value_map),
144
+ )
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end