lutaml-model 0.8.44 → 0.8.46
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/docs/_guides/advanced-mapping.adoc +69 -0
- data/lib/compat/opal/lutaml_model_boot.rb +1 -0
- data/lib/lutaml/key_value/mapping.rb +32 -6
- data/lib/lutaml/key_value/mapping_rule.rb +9 -0
- data/lib/lutaml/key_value/transform.rb +186 -7
- data/lib/lutaml/key_value/transformation/rule_compiler.rb +2 -0
- data/lib/lutaml/key_value/transformation.rb +113 -2
- data/lib/lutaml/model/error/unknown_discriminator_error.rb +11 -0
- data/lib/lutaml/model/mapping/mapping.rb +30 -0
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/model.rb +2 -0
- data/lib/lutaml/xml/mapping.rb +3 -14
- data/lib/lutaml/xml/mapping_rule.rb +7 -1
- data/lib/lutaml/xml/model_transform.rb +32 -0
- data/lib/lutaml/xml/parse_session.rb +36 -14
- data/spec/lutaml/key_value/when_attribute_spec.rb +348 -0
- data/spec/lutaml/xml/when_attribute_unmatched_spec.rb +169 -0
- metadata +4 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
# lutaml-model#88: `unmatched: :raise` on a when_attribute rule fails the
|
|
6
|
+
# parse when an occurrence is claimed by no rule — no discriminator match
|
|
7
|
+
# and no plain sibling on the wire name. The default (:drop) keeps the
|
|
8
|
+
# silent-drop behavior.
|
|
9
|
+
class UnmatchedComponent < Lutaml::Model::Serializable
|
|
10
|
+
attribute :text, :string
|
|
11
|
+
|
|
12
|
+
xml do
|
|
13
|
+
element "component"
|
|
14
|
+
map_element "text", to: :text
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class UnmatchedRequirement < Lutaml::Model::Serializable
|
|
19
|
+
attribute :guidance, UnmatchedComponent, collection: true
|
|
20
|
+
attribute :purpose, UnmatchedComponent, collection: true
|
|
21
|
+
|
|
22
|
+
xml do
|
|
23
|
+
element "requirement"
|
|
24
|
+
map_element "component", to: :guidance,
|
|
25
|
+
when_attribute: { "type" => "guidance" },
|
|
26
|
+
unmatched: :raise
|
|
27
|
+
map_element "component", to: :purpose,
|
|
28
|
+
when_attribute: { "type" => "purpose" }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
RSpec.describe "when_attribute unmatched policy" do
|
|
33
|
+
before do
|
|
34
|
+
stub_const("Unmatched::Component", UnmatchedComponent)
|
|
35
|
+
stub_const("Unmatched::Requirement", UnmatchedRequirement)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "parses when every occurrence is covered" do
|
|
39
|
+
req = UnmatchedRequirement.from_xml(<<~XML)
|
|
40
|
+
<requirement>
|
|
41
|
+
<component type="guidance"><text>g1</text></component>
|
|
42
|
+
<component type="purpose"><text>p1</text></component>
|
|
43
|
+
</requirement>
|
|
44
|
+
XML
|
|
45
|
+
|
|
46
|
+
expect(req.guidance.map(&:text)).to eq(["g1"])
|
|
47
|
+
expect(req.purpose.map(&:text)).to eq(["p1"])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "raises on an unknown discriminator value" do
|
|
51
|
+
xml = <<~XML
|
|
52
|
+
<requirement>
|
|
53
|
+
<component type="guidance"><text>g1</text></component>
|
|
54
|
+
<component type="unknown"><text>x</text></component>
|
|
55
|
+
</requirement>
|
|
56
|
+
XML
|
|
57
|
+
|
|
58
|
+
expect { UnmatchedRequirement.from_xml(xml) }
|
|
59
|
+
.to raise_error(Lutaml::Model::UnknownDiscriminatorError, /type="unknown"/)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "raises when the discriminator attribute is missing entirely" do
|
|
63
|
+
xml = "<requirement><component><text>x</text></component></requirement>"
|
|
64
|
+
|
|
65
|
+
expect { UnmatchedRequirement.from_xml(xml) }
|
|
66
|
+
.to raise_error(Lutaml::Model::UnknownDiscriminatorError, /<component>/)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "names the tested attributes of the unclaimed occurrence" do
|
|
70
|
+
xml = '<requirement><component type="later"><text>x</text></component></requirement>'
|
|
71
|
+
|
|
72
|
+
expect { UnmatchedRequirement.from_xml(xml) }
|
|
73
|
+
.to raise_error(Lutaml::Model::UnknownDiscriminatorError, /unmatched: :drop/)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "does not raise when a plain rule claims the leftovers" do
|
|
77
|
+
both = Class.new(Lutaml::Model::Serializable) do
|
|
78
|
+
attribute :special, UnmatchedComponent, collection: true
|
|
79
|
+
attribute :plain, UnmatchedComponent, collection: true
|
|
80
|
+
|
|
81
|
+
xml do
|
|
82
|
+
element "holder"
|
|
83
|
+
map_element "item", to: :special,
|
|
84
|
+
when_attribute: { "kind" => "special" },
|
|
85
|
+
unmatched: :raise
|
|
86
|
+
map_element "item", to: :plain
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
stub_const("Unmatched::Holder", both)
|
|
90
|
+
|
|
91
|
+
doc = both.from_xml(
|
|
92
|
+
'<holder><item kind="special"><text>b</text></item><item><text>a</text></item></holder>',
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
expect(doc.special.map(&:text)).to eq(["b"])
|
|
96
|
+
expect(doc.plain.map(&:text)).to eq(["a"])
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "drops unmatched occurrences by default" do
|
|
100
|
+
lenient = Class.new(Lutaml::Model::Serializable) do
|
|
101
|
+
attribute :guidance, UnmatchedComponent, collection: true
|
|
102
|
+
|
|
103
|
+
xml do
|
|
104
|
+
element "requirement"
|
|
105
|
+
map_element "component", to: :guidance,
|
|
106
|
+
when_attribute: { "type" => "guidance" }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
stub_const("Unmatched::Lenient", lenient)
|
|
110
|
+
|
|
111
|
+
doc = lenient.from_xml(
|
|
112
|
+
'<requirement><component type="guidance"><text>g</text></component>' \
|
|
113
|
+
'<component type="other"><text>x</text></component></requirement>',
|
|
114
|
+
)
|
|
115
|
+
expect(doc.guidance.map(&:text)).to eq(["g"])
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "survives deep_dup of mappings" do
|
|
119
|
+
rule = UnmatchedRequirement.mappings_for(:xml).mappings.find do |r|
|
|
120
|
+
r.to == :guidance
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
expect(rule.unmatched).to eq(:raise)
|
|
124
|
+
duped = rule.deep_dup
|
|
125
|
+
expect(duped.unmatched).to eq(:raise)
|
|
126
|
+
expect(duped.when_attribute).to eq("type" => "guidance")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "rejects unknown policy values" do
|
|
130
|
+
expect do
|
|
131
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
132
|
+
attribute :x, :string
|
|
133
|
+
|
|
134
|
+
xml do
|
|
135
|
+
element "x"
|
|
136
|
+
map_element "x", to: :x,
|
|
137
|
+
when_attribute: { "type" => "a" },
|
|
138
|
+
unmatched: :explode
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end.to raise_error(Lutaml::Model::IncorrectMappingArgumentsError, /unmatched/)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "rejects unmatched without when_attribute" do
|
|
145
|
+
expect do
|
|
146
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
147
|
+
attribute :x, :string
|
|
148
|
+
|
|
149
|
+
xml do
|
|
150
|
+
element "x"
|
|
151
|
+
map_element "x", to: :x, unmatched: :raise
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end.to raise_error(Lutaml::Model::IncorrectMappingArgumentsError, /when_attribute/)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "is rejected on attribute mappings" do
|
|
158
|
+
expect do
|
|
159
|
+
Class.new(Lutaml::Model::Serializable) do
|
|
160
|
+
attribute :x, :string
|
|
161
|
+
|
|
162
|
+
xml do
|
|
163
|
+
element "x"
|
|
164
|
+
map_attribute "x", to: :x, unmatched: :raise
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end.to raise_error(ArgumentError)
|
|
168
|
+
end
|
|
169
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.46
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -489,6 +489,7 @@ files:
|
|
|
489
489
|
- lib/lutaml/model/error/undefined_attribute_error.rb
|
|
490
490
|
- lib/lutaml/model/error/union_schema_unsupported_error.rb
|
|
491
491
|
- lib/lutaml/model/error/unknown_adapter_type_error.rb
|
|
492
|
+
- lib/lutaml/model/error/unknown_discriminator_error.rb
|
|
492
493
|
- lib/lutaml/model/error/unknown_sequence_mapping_error.rb
|
|
493
494
|
- lib/lutaml/model/error/unknown_type_error.rb
|
|
494
495
|
- lib/lutaml/model/error/unresolvable_type_error.rb
|
|
@@ -1687,6 +1688,7 @@ files:
|
|
|
1687
1688
|
- spec/lutaml/key_value/transformation/rule_compiler_spec.rb
|
|
1688
1689
|
- spec/lutaml/key_value/transformation/value_serializer_spec.rb
|
|
1689
1690
|
- spec/lutaml/key_value/transformation_spec.rb
|
|
1691
|
+
- spec/lutaml/key_value/when_attribute_spec.rb
|
|
1690
1692
|
- spec/lutaml/model/absent_value_contracts_spec.rb
|
|
1691
1693
|
- spec/lutaml/model/adapter_resolver_configured_spec.rb
|
|
1692
1694
|
- spec/lutaml/model/attribute_apply_value_map_spec.rb
|
|
@@ -2008,6 +2010,7 @@ files:
|
|
|
2008
2010
|
- spec/lutaml/xml/w3c_types_spec.rb
|
|
2009
2011
|
- spec/lutaml/xml/when_attribute_ordered_spec.rb
|
|
2010
2012
|
- spec/lutaml/xml/when_attribute_spec.rb
|
|
2013
|
+
- spec/lutaml/xml/when_attribute_unmatched_spec.rb
|
|
2011
2014
|
- spec/lutaml/xml/xml_adapter_spec.rb
|
|
2012
2015
|
- spec/lutaml/xml/xml_declaration_spec.rb
|
|
2013
2016
|
- spec/lutaml/xml/xml_element_guard_spec.rb
|