lutaml-model 0.3.10 → 0.3.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5140f93f22f4b05222edc408aeca50552082e447b71fddd724b34ba9e6b82d55
4
- data.tar.gz: 0aa44a3c72b65cca0ed2b7411614d8cdb0c44b4e8293e183935cb45ba7818d7c
3
+ metadata.gz: 5b36d07a850d4736c0634735a198f05dd34c49b906cd1265b3dd49266931eb22
4
+ data.tar.gz: cefd0559ad4010ecd2ab0a547ab87493b4958a480f6cb19ab317c248836b8f75
5
5
  SHA512:
6
- metadata.gz: 69e4d0d0a3a5bd19e11a43fd33e03566ca035d18cf948a0a2fc5abe5f880489e4a6ad347d8118a04c35c8c95be5b7eb29ca93d426643c7790ab045db2b34721c
7
- data.tar.gz: df1699ba6647f53f97735d0986b92bf8f76d6bf44430117406100b257f5934ac4a7baa6a4243bb8384db277ecb975bf64efe2f1a16b293739b245150e800cb15
6
+ metadata.gz: 83fac7632d0eec4f5bd4339132b36d267877932cf34839eac6dbdefd0cd0e551988b73b3cd379b856af0df351e42694c157342efd8baba67e283e71d34b88171
7
+ data.tar.gz: 6befe6bfce13fb6175a04f8e0ac81794304d3c56c51feea343334c501346cba517db1f89ab3387ea3300e546d160d24af264048e9762c85debc4063300d57025
data/.rubocop_todo.yml CHANGED
@@ -1,25 +1,18 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-09-10 23:53:08 UTC using RuboCop version 1.66.1.
3
+ # on 2024-10-23 12:15:48 UTC using RuboCop version 1.66.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 88
9
+ # Offense count: 139
10
10
  # This cop supports safe autocorrection (--autocorrect).
11
11
  # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
12
12
  # URISchemes: http, https
13
13
  Layout/LineLength:
14
14
  Enabled: false
15
15
 
16
- # Offense count: 1
17
- # This cop supports safe autocorrection (--autocorrect).
18
- # Configuration parameters: AllowInHeredoc.
19
- Layout/TrailingWhitespace:
20
- Exclude:
21
- - 'lib/lutaml/model/schema_location.rb'
22
-
23
16
  # Offense count: 11
24
17
  # Configuration parameters: AllowedMethods.
25
18
  # AllowedMethods: enums
@@ -37,12 +30,13 @@ Lint/DuplicateMethods:
37
30
  Exclude:
38
31
  - 'lib/lutaml/model/attribute.rb'
39
32
 
40
- # Offense count: 31
33
+ # Offense count: 37
41
34
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
42
35
  Metrics/AbcSize:
43
36
  Exclude:
44
37
  - 'lib/lutaml/model/attribute.rb'
45
38
  - 'lib/lutaml/model/comparable_model.rb'
39
+ - 'lib/lutaml/model/mapping_rule.rb'
46
40
  - 'lib/lutaml/model/schema/relaxng_schema.rb'
47
41
  - 'lib/lutaml/model/schema/xsd_schema.rb'
48
42
  - 'lib/lutaml/model/serialize.rb'
@@ -50,14 +44,15 @@ Metrics/AbcSize:
50
44
  - 'lib/lutaml/model/xml_adapter/nokogiri_adapter.rb'
51
45
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
52
46
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
47
+ - 'lib/lutaml/model/xml_mapping_rule.rb'
53
48
 
54
49
  # Offense count: 6
55
50
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
56
51
  # AllowedMethods: refine
57
52
  Metrics/BlockLength:
58
- Max: 42
53
+ Max: 47
59
54
 
60
- # Offense count: 25
55
+ # Offense count: 27
61
56
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
62
57
  Metrics/CyclomaticComplexity:
63
58
  Exclude:
@@ -69,17 +64,17 @@ Metrics/CyclomaticComplexity:
69
64
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
70
65
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
71
66
 
72
- # Offense count: 39
67
+ # Offense count: 50
73
68
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
74
69
  Metrics/MethodLength:
75
- Max: 49
70
+ Max: 51
76
71
 
77
72
  # Offense count: 4
78
73
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
79
74
  Metrics/ParameterLists:
80
- Max: 9
75
+ Max: 12
81
76
 
82
- # Offense count: 21
77
+ # Offense count: 22
83
78
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
84
79
  Metrics/PerceivedComplexity:
85
80
  Exclude:
@@ -90,7 +85,7 @@ Metrics/PerceivedComplexity:
90
85
  - 'lib/lutaml/model/xml_adapter/ox_adapter.rb'
91
86
  - 'lib/lutaml/model/xml_adapter/xml_document.rb'
92
87
 
93
- # Offense count: 7
88
+ # Offense count: 8
94
89
  # Configuration parameters: Prefixes, AllowedPatterns.
95
90
  # Prefixes: when, with, without
96
91
  RSpec/ContextWording:
@@ -99,11 +94,12 @@ RSpec/ContextWording:
99
94
  - 'spec/lutaml/model/xml_adapter/oga_adapter_spec.rb'
100
95
  - 'spec/lutaml/model/xml_adapter/ox_adapter_spec.rb'
101
96
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
97
+ - 'spec/lutaml/model/xml_mapping_spec.rb'
102
98
 
103
- # Offense count: 101
99
+ # Offense count: 109
104
100
  # Configuration parameters: CountAsOne.
105
101
  RSpec/ExampleLength:
106
- Max: 57
102
+ Max: 54
107
103
 
108
104
  # Offense count: 2
109
105
  # Configuration parameters: Max, AllowedIdentifiers, AllowedPatterns.
@@ -129,11 +125,11 @@ RSpec/MultipleDescribes:
129
125
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
130
126
  - 'spec/lutaml/model/xml_adapter_spec.rb'
131
127
 
132
- # Offense count: 88
128
+ # Offense count: 119
133
129
  RSpec/MultipleExpectations:
134
- Max: 11
130
+ Max: 14
135
131
 
136
- # Offense count: 17
132
+ # Offense count: 18
137
133
  # Configuration parameters: AllowSubject.
138
134
  RSpec/MultipleMemoizedHelpers:
139
135
  Max: 9
@@ -147,18 +143,24 @@ RSpec/PendingWithoutReason:
147
143
  - 'spec/lutaml/model/xml_adapter/xml_namespace_spec.rb'
148
144
  - 'spec/lutaml/model/xml_adapter_spec.rb'
149
145
 
146
+ # Offense count: 1
147
+ RSpec/RemoveConst:
148
+ Exclude:
149
+ - 'spec/lutaml/model/type/decimal_spec.rb'
150
+
150
151
  # Offense count: 2
151
152
  RSpec/RepeatedExampleGroupDescription:
152
153
  Exclude:
153
154
  - 'spec/lutaml/model/collection_spec.rb'
154
155
 
155
- # Offense count: 1
156
+ # Offense count: 2
156
157
  # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata.
157
158
  # Include: **/*_spec.rb
158
159
  RSpec/SpecFilePathFormat:
159
160
  Exclude:
160
161
  - '**/spec/routing/**/*'
161
162
  - 'spec/lutaml/model/collection_spec.rb'
163
+ - 'spec/lutaml/model/type/decimal_spec.rb'
162
164
 
163
165
  # Offense count: 1
164
166
  Security/CompoundHash:
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in lutaml-model.gemspec
6
6
  gemspec
7
7
 
8
+ gem "bigdecimal"
8
9
  gem "equivalent-xml"
9
10
  gem "multi_json"
10
11
  gem "nokogiri"
data/LICENSE.md ADDED
@@ -0,0 +1,33 @@
1
+ Licenses & Copyright
2
+ ====================
3
+
4
+ This license file adheres to the formatting guidelines of
5
+ [readable-licenses](https://github.com/nevir/readable-licenses).
6
+
7
+
8
+ Ribose's BSD 2-Clause License
9
+ -----------------------------
10
+
11
+ Copyright (c) 2024, [Ribose Inc](https://www.ribose.com).
12
+ All rights reserved.
13
+
14
+ Redistribution and use in source and binary forms, with or without modification,
15
+ are permitted provided that the following conditions are met:
16
+
17
+ 1. Redistributions of source code must retain the above copyright notice,
18
+ this list of conditions and the following disclaimer.
19
+
20
+ 2. Redistributions in binary form must reproduce the above copyright notice,
21
+ this list of conditions and the following disclaimer in the documentation
22
+ and/or other materials provided with the distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
28
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.adoc CHANGED
@@ -145,6 +145,8 @@ same class and all their attributes are equal.
145
145
 
146
146
  === Supported attribute value types
147
147
 
148
+ ==== General types
149
+
148
150
  Lutaml::Model supports the following attribute types, they can be
149
151
  referred by a string, a symbol, or their class constant.
150
152
 
@@ -166,12 +168,11 @@ attribute :name_of_attribute, {symbol | string | class}
166
168
  | `DateTime` | `:date_time` | `Lutaml::Model::Type::DateTime` | `::DateTime`
167
169
  | `TimeWithoutDate` | `:time_without_date` | `Lutaml::Model::Type::TimeWithoutDate` | `::Time`
168
170
  | `Boolean` | `:boolean` | `Lutaml::Model::Type::Boolean` | `Boolean`
169
- | `Decimal` | `:decimal` | `Lutaml::Model::Type::Decimal` | `::BigDecimal`
171
+ | `Decimal` (optional) | `:decimal` | `Lutaml::Model::Type::Decimal` | `::BigDecimal`
170
172
  | `Hash` | `:hash` | `Lutaml::Model::Type::Hash` | `::Hash`
171
173
 
172
174
  |===
173
175
 
174
-
175
176
  .Defining attributes with supported types via symbol, string and class
176
177
  [example]
177
178
  ====
@@ -198,6 +199,23 @@ end
198
199
  ----
199
200
  ====
200
201
 
202
+ ==== (optional) Decimal type
203
+
204
+ The `BigDecimal` class is no longer part of the standard Ruby library from Ruby
205
+ 3.4 onwards, hence the `Decimal` type is only enabled when the `bigdecimal`
206
+ library is loaded.
207
+
208
+ This means that the following code needs to be run before using (and parsing)
209
+ the `Decimal` type:
210
+
211
+ [source,ruby]
212
+ ----
213
+ require 'bigdecimal'
214
+ ----
215
+
216
+ If the `bigdecimal` library is not loaded, usage of the `Decimal` type will
217
+ raise a `Lutaml::Model::TypeNotSupportedError`.
218
+
201
219
 
202
220
  === Attribute as a collection
203
221
 
@@ -405,6 +423,51 @@ end
405
423
  ----
406
424
  ====
407
425
 
426
+ === Attribute as raw string
427
+
428
+ An attribute can be set to read the value as raw string for XML, by using the `raw: true` option.
429
+
430
+ Syntax:
431
+
432
+ [source,ruby]
433
+ ----
434
+ attribute :name_of_attribute, :string, raw: true
435
+ ----
436
+
437
+ .Using the `raw` option to read raw value for an XML attribute
438
+ [example]
439
+ ====
440
+ [source,ruby]
441
+ ----
442
+ class Person < Lutaml::Model::Serializable
443
+ attribute :name, :string
444
+ attribute :description, :string, raw: true
445
+ end
446
+ ----
447
+
448
+ For the following xml
449
+ [source,xml]
450
+ ----
451
+ <Person>
452
+ <name>John Doe</name>
453
+ <description>
454
+ A <b>fictional person</b> commonly used as a <i>placeholder name</i>.
455
+ </description>
456
+ </Person>
457
+ ----
458
+
459
+ [source,ruby]
460
+ ----
461
+ > Person.from_xml(xml)
462
+ > # <Person:0x0000000107a3ca70
463
+ @description="\n A <b>fictional person</b> commonly used as a <i>placeholder name</i>.\n ",
464
+ @element_order=["text", "name", "text", "description", "text"],
465
+ @name="John Doe",
466
+ @ordered=nil,
467
+ @validate_on_set=false>
468
+ ----
469
+ ====
470
+
408
471
  == Serialization model mappings
409
472
 
410
473
  === General
@@ -594,7 +657,7 @@ end
594
657
 
595
658
  [source,xml]
596
659
  ----
597
- <example value=12><name>John Doe</name></example>
660
+ <example value="12"><name>John Doe</name></example>
598
661
  ----
599
662
 
600
663
  [source,ruby]
@@ -604,6 +667,37 @@ end
604
667
  > Example.new(value: 12).to_xml
605
668
  > #<example value="12"></example>
606
669
  ----
670
+
671
+ The map_attribute method does not inherit the root element's namespace. If you need to specify a namespace for an attribute,
672
+ you must explicitly declare the namespace and prefix in the map_attribute method.
673
+ [example]
674
+ ====
675
+ The following class will parse the XML snippet below:
676
+
677
+ [source,ruby]
678
+ ----
679
+ class Attribute < Lutaml::Model::Serializable
680
+ attribute :value, :integer
681
+
682
+ xml do
683
+ root 'example'
684
+ map_attribute 'value', to: :value, namespace: "http://www.tech.co/XMI", prefix: "xl"
685
+ end
686
+ end
687
+ ----
688
+
689
+ [source,xml]
690
+ ----
691
+ <example xl:value="20" xmlns:xl="http://www.tech.co/XMI"></example>
692
+ ----
693
+
694
+ [source,ruby]
695
+ ----
696
+ > Attribute.from_xml(xml)
697
+ > #<Attribute:0x0000000109436db8 @value=20>
698
+ > Attribute.new(value: 20).to_xml
699
+ > #<example xmlns:xl=\"http://www.tech.co/XMI\" xl:value=\"20\"/>
700
+ ----
607
701
  ====
608
702
 
609
703
 
@@ -680,7 +774,7 @@ end
680
774
 
681
775
  [source,xml]
682
776
  ----
683
- <example value=12><name>John Doe</name> is my moniker.</example>
777
+ <example value="12"><name>John Doe</name> is my moniker.</example>
684
778
  ----
685
779
 
686
780
  [source,ruby]
@@ -989,7 +1083,7 @@ end
989
1083
 
990
1084
  TODO: How to create mixed content from `#new`?
991
1085
 
992
-
1086
+ [[xml-schema-location]]
993
1087
  ==== Automatic support of `xsi:schemaLocation`
994
1088
 
995
1089
  The
@@ -1444,9 +1538,14 @@ NOTE: The corresponding keyword used by Shale is `receiver:` instead of
1444
1538
 
1445
1539
  ==== Attribute serialization with custom methods
1446
1540
 
1541
+ ===== General
1542
+
1447
1543
  Define custom methods for specific attribute mappings using the `with:` key for
1448
1544
  each serialization mapping block for `from` and `to`.
1449
1545
 
1546
+
1547
+ ===== XML serialization with custom methods
1548
+
1450
1549
  Syntax:
1451
1550
 
1452
1551
  .XML serialization with custom methods
@@ -1468,6 +1567,81 @@ xml do
1468
1567
  end
1469
1568
  ----
1470
1569
 
1570
+ .Using the `with:` key to define custom serialization methods for XML
1571
+ [example]
1572
+ ====
1573
+ The following class will parse the XML snippet below:
1574
+
1575
+ [source,ruby]
1576
+ ----
1577
+ class CustomCeramic < Lutaml::Model::Serializable
1578
+ attribute :name, :string
1579
+ attribute :size, :integer
1580
+ attribute :description, :string
1581
+
1582
+ xml do
1583
+ map_element "Name", to: :name, with: { to: :name_to_xml, from: :name_from_xml }
1584
+ map_attribute "Size", to: :size, with: { to: :size_to_xml, from: :size_from_xml }
1585
+ map_content with: { to: :description_to_xml, from: :description_from_xml }
1586
+ end
1587
+
1588
+ def name_to_xml(model, parent, doc)
1589
+ el = doc.create_element("Name")
1590
+ doc.add_text(el, "XML Masterpiece: #{model.name}")
1591
+ doc.add_element(parent, el)
1592
+ end
1593
+
1594
+ def name_from_xml(model, value)
1595
+ model.name = value.sub(/^XML Masterpiece: /, "")
1596
+ end
1597
+
1598
+ def size_to_xml(model, parent, doc)
1599
+ doc.add_attribute(parent, "Size", model.size + 3)
1600
+ end
1601
+
1602
+ def size_from_xml(model, value)
1603
+ model.size = value.to_i - 3
1604
+ end
1605
+
1606
+ def description_to_xml(model, parent, doc)
1607
+ doc.add_text(parent, "XML Description: #{model.description}")
1608
+ end
1609
+
1610
+ def description_from_xml(model, value)
1611
+ model.description = value.join.strip.sub(/^XML Description: /, "")
1612
+ end
1613
+ end
1614
+ ----
1615
+
1616
+ [source,xml]
1617
+ ----
1618
+ <CustomCeramic Size="15">
1619
+ <Name>XML Masterpiece: Vase</Name>
1620
+ XML Description: A beautiful ceramic vase
1621
+ </CustomCeramic>
1622
+ ----
1623
+
1624
+ [source,ruby]
1625
+ ----
1626
+ > CustomCeramic.from_xml(xml)
1627
+ > #<CustomCeramic:0x0000000108d0e1f8
1628
+ @element_order=["text", "Name", "text", "Size", "text"],
1629
+ @name="Masterpiece: Vase",
1630
+ @ordered=nil,
1631
+ @size=12,
1632
+ @description="A beautiful ceramic vase",
1633
+ @validate_on_set=false>
1634
+ > puts CustomCeramic.new(name: "Vase", size: 12, description: "A beautiful vase").to_xml
1635
+ # <CustomCeramic Size="15">
1636
+ # <Name>XML Masterpiece: Vase</Name>
1637
+ # XML Description: A beautiful vase
1638
+ # </CustomCeramic>
1639
+ ----
1640
+ ====
1641
+
1642
+
1643
+ ===== Key-value data model serialization with custom methods
1644
+
1471
1645
  .Key-value data model serialization with custom methods
1472
1646
  [source,ruby]
1473
1647
  ----
@@ -1524,7 +1698,7 @@ end
1524
1698
 
1525
1699
 
1526
1700
  [[attribute-extraction]]
1527
- ==== Attribute extraction
1701
+ ==== Attribute extraction (for key-value data models only)
1528
1702
 
1529
1703
  NOTE: This feature is for key-value data model serialization only.
1530
1704
 
@@ -1992,9 +2166,9 @@ differences in implementation.
1992
2166
  |
1993
2167
 
1994
2168
  | Value types
1995
- | `Lutaml::Model::Type` includes: `Integer`, `String`, `Float`, `Boolean`, `Date`, `DateTime`, `Time`, `Hash`.
2169
+ | `Lutaml::Model::Type` includes: `Integer`, `String`, `Float`, `Boolean`, `Date`, `DateTime`, `Time`, `Decimal`, `Hash`.
1996
2170
  | `Shale::Type` includes: `Integer`, `String`, `Float`, `Boolean`, `Date`, `Time`.
1997
- | Lutaml::Model supports the additional value types `DateTime` and `Hash`.
2171
+ | Lutaml::Model supports additional value types `Decimal`, `DateTime` and `Hash`.
1998
2172
 
1999
2173
  | Configuration
2000
2174
  | `Lutaml::Model::Config`
@@ -2011,6 +2185,11 @@ differences in implementation.
2011
2185
  | XML, YAML, JSON, TOML, CSV
2012
2186
  | Lutaml::Model does not support CSV.
2013
2187
 
2188
+ | Validation
2189
+ | Supports collection range, fixed values, and custom validation
2190
+ | Requires implementation
2191
+ |
2192
+
2014
2193
  | Adapter support
2015
2194
  | XML (Nokogiri, Ox, Oga), YAML, JSON (JSON, MultiJson), TOML (Toml-rb, Tomlib)
2016
2195
  | XML (Nokogiri, Ox), YAML, JSON (JSON, MultiJson), TOML (Toml-rb, Tomlib), CSV
@@ -2042,6 +2221,12 @@ namespace from the root element.
2042
2221
  | No.
2043
2222
  |
2044
2223
 
2224
+ | Support for `xsi:schemaLocation`
2225
+ | Yes. Automatically supports the <<xml-schema-location,`xsi:schemaLocation`>>
2226
+ attribute for every element.
2227
+ | Requires manual specification on every XML element that uses it.
2228
+ |
2229
+
2045
2230
  4+h| Attribute features
2046
2231
 
2047
2232
  | Attribute delegation
@@ -2061,7 +2246,6 @@ data models.
2061
2246
  | No.
2062
2247
  | Lutaml::Model supports attribute extraction from key-value data models.
2063
2248
 
2064
-
2065
2249
  |===
2066
2250
 
2067
2251
 
@@ -2114,25 +2298,26 @@ Actions:
2114
2298
 
2115
2299
  === Step 2: Replace value type definitions
2116
2300
 
2117
- Value types in `Lutaml::Model` are under the `Lutaml::Model::Type` module.
2301
+ Value types in `Lutaml::Model` are under the `Lutaml::Model::Type` module,
2302
+ or use the LutaML type symbols.
2118
2303
 
2119
2304
  [source,ruby]
2120
2305
  ----
2121
2306
  class Example < Lutaml::Model::Serializable
2122
- attribute :length, Lutaml::Model::Type::Integer
2123
- attribute :description, Lutaml::Model::Type::String
2307
+ attribute :length, :integer
2308
+ attribute :description, :string
2124
2309
  end
2125
2310
  ----
2126
2311
 
2127
2312
  [NOTE]
2128
2313
  ====
2129
- `Lutaml::Model` also supports specifying predefined value types as strings or
2314
+ `Lutaml::Model` supports specifying predefined value types as strings or
2130
2315
  symbols, which is not supported by Shale.
2131
2316
 
2132
2317
  [source,ruby]
2133
2318
  ----
2134
2319
  class Example < Lutaml::Model::Serializable
2135
- attribute :length, :integer
2320
+ attribute :length, Lutaml::Model::Type::Integer
2136
2321
  attribute :description, "String"
2137
2322
  end
2138
2323
  ----
@@ -2369,6 +2554,6 @@ allowing you to shape and structure your data into useful forms.
2369
2554
  == License and Copyright
2370
2555
 
2371
2556
  This project is licensed under the BSD 2-clause License.
2372
- See the LICENSE file for details.
2557
+ See the link:LICENSE.md[] file for details.
2373
2558
 
2374
2559
  Copyright Ribose.
@@ -7,6 +7,7 @@ module Lutaml
7
7
  @name = name
8
8
  @type = cast_type(type)
9
9
  @options = options
10
+ @raw = !!options[:raw]
10
11
 
11
12
  if collection?
12
13
  validate_collection_range
@@ -14,6 +15,10 @@ module Lutaml
14
15
  end
15
16
  end
16
17
 
18
+ def delegate
19
+ @options[:delegate]
20
+ end
21
+
17
22
  def cast_type(type)
18
23
  case type
19
24
  when Class
@@ -27,6 +32,16 @@ module Lutaml
27
32
  raise ArgumentError, "Unknown Lutaml::Model::Type: #{type}"
28
33
  end
29
34
 
35
+ def cast_value(value)
36
+ return type.cast(value) unless value.is_a?(Array)
37
+
38
+ value.map { |v| type.cast(v) }
39
+ end
40
+
41
+ def setter
42
+ :"#{@name}="
43
+ end
44
+
30
45
  def collection?
31
46
  options[:collection] || false
32
47
  end
@@ -35,10 +50,20 @@ module Lutaml
35
50
  !collection?
36
51
  end
37
52
 
38
- def default
39
- return options[:default].call if options[:default].is_a?(Proc)
53
+ def raw?
54
+ @raw
55
+ end
40
56
 
41
- options[:default]
57
+ def default
58
+ value = if delegate
59
+ type.attributes[to].default
60
+ elsif options[:default].is_a?(Proc)
61
+ options[:default].call
62
+ else
63
+ options[:default]
64
+ end
65
+
66
+ cast_value(value)
42
67
  end
43
68
 
44
69
  def render_nil?
@@ -0,0 +1,6 @@
1
+ module Lutaml
2
+ module Model
3
+ class IncorrectMappingArgumentsError < Error
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module Lutaml
2
+ module Model
3
+ class TypeNotEnabledError < Error
4
+ def initialize(type_name, value)
5
+ super("#{type_name} type is not enabled. Value: #{value}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -6,6 +6,8 @@ module Lutaml
6
6
  end
7
7
 
8
8
  require_relative "error/invalid_value_error"
9
+ require_relative "error/incorrect_mapping_argument_error"
9
10
  require_relative "error/unknown_adapter_type_error"
10
11
  require_relative "error/collection_count_out_of_range_error"
11
12
  require_relative "error/validation_error"
13
+ require_relative "error/type_not_enabled_error"
@@ -6,8 +6,7 @@ module Lutaml
6
6
  module JsonAdapter
7
7
  class StandardJsonAdapter < JsonDocument
8
8
  def self.parse(json)
9
- attributes = JSON.parse(json, create_additions: false)
10
- new(attributes)
9
+ JSON.parse(json, create_additions: false)
11
10
  end
12
11
 
13
12
  def to_json(*args)
@@ -11,12 +11,14 @@ module Lutaml
11
11
 
12
12
  def map(
13
13
  name,
14
- to:,
14
+ to: nil,
15
15
  render_nil: false,
16
16
  with: {},
17
17
  delegate: nil,
18
18
  child_mappings: nil
19
19
  )
20
+ validate!(name, to, with)
21
+
20
22
  @mappings << KeyValueMappingRule.new(
21
23
  name,
22
24
  to: to,
@@ -28,6 +30,28 @@ module Lutaml
28
30
  end
29
31
 
30
32
  alias map_element map
33
+
34
+ def validate!(key, to, with)
35
+ if to.nil? && with.empty?
36
+ msg = ":to or :with argument is required for mapping '#{key}'"
37
+ raise IncorrectMappingArgumentsError.new(msg)
38
+ end
39
+
40
+ if !with.empty? && (with[:from].nil? || with[:to].nil?)
41
+ msg = ":with argument for mapping '#{key}' requires :to and :from keys"
42
+ raise IncorrectMappingArgumentsError.new(msg)
43
+ end
44
+ end
45
+
46
+ def deep_dup
47
+ self.class.new.tap do |new_mapping|
48
+ new_mapping.instance_variable_set(:@mappings, duplicate_mappings)
49
+ end
50
+ end
51
+
52
+ def duplicate_mappings
53
+ @mappings.map(&:deep_dup)
54
+ end
31
55
  end
32
56
  end
33
57
  end