lutaml-model 0.1.0
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 +7 -0
- data/.github/workflows/main.yml +27 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +23 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +12 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +12 -0
- data/README.adoc +380 -0
- data/Rakefile +12 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/lutaml/model/attribute.rb +26 -0
- data/lib/lutaml/model/config.rb +14 -0
- data/lib/lutaml/model/json_adapter/multi_json.rb +20 -0
- data/lib/lutaml/model/json_adapter/standard.rb +20 -0
- data/lib/lutaml/model/json_adapter.rb +38 -0
- data/lib/lutaml/model/key_value_mapping.rb +20 -0
- data/lib/lutaml/model/key_value_mapping_rule.rb +10 -0
- data/lib/lutaml/model/mapping_rule.rb +34 -0
- data/lib/lutaml/model/schema/json_schema.rb +63 -0
- data/lib/lutaml/model/schema/relaxng_schema.rb +50 -0
- data/lib/lutaml/model/schema/xsd_schema.rb +54 -0
- data/lib/lutaml/model/schema/yaml_schema.rb +47 -0
- data/lib/lutaml/model/schema.rb +27 -0
- data/lib/lutaml/model/serializable.rb +10 -0
- data/lib/lutaml/model/serialize.rb +179 -0
- data/lib/lutaml/model/toml_adapter/toml_rb_adapter.rb +20 -0
- data/lib/lutaml/model/toml_adapter/tomlib_adapter.rb +20 -0
- data/lib/lutaml/model/toml_adapter.rb +37 -0
- data/lib/lutaml/model/type/time_without_date.rb +17 -0
- data/lib/lutaml/model/type.rb +114 -0
- data/lib/lutaml/model/version.rb +7 -0
- data/lib/lutaml/model/xml_adapter/nokogiri_adapter.rb +117 -0
- data/lib/lutaml/model/xml_adapter/oga_adapter.rb +75 -0
- data/lib/lutaml/model/xml_adapter/ox_adapter.rb +75 -0
- data/lib/lutaml/model/xml_adapter.rb +60 -0
- data/lib/lutaml/model/xml_mapping.rb +65 -0
- data/lib/lutaml/model/xml_mapping_rule.rb +16 -0
- data/lib/lutaml/model/yaml_adapter.rb +24 -0
- data/lib/lutaml/model.rb +21 -0
- data/lutaml-model.gemspec +50 -0
- data/sig/lutaml/model.rbs +6 -0
- metadata +228 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
# lib/lutaml/model/type.rb
|
2
|
+
require "date"
|
3
|
+
require "bigdecimal"
|
4
|
+
require "securerandom"
|
5
|
+
require "uri"
|
6
|
+
require "ipaddr"
|
7
|
+
require "json"
|
8
|
+
|
9
|
+
module Lutaml
|
10
|
+
module Model
|
11
|
+
module Type
|
12
|
+
class Boolean; end
|
13
|
+
|
14
|
+
%w(String
|
15
|
+
Integer
|
16
|
+
Float
|
17
|
+
Date
|
18
|
+
Time
|
19
|
+
Boolean
|
20
|
+
Decimal
|
21
|
+
Hash
|
22
|
+
UUID
|
23
|
+
Symbol
|
24
|
+
BigInteger
|
25
|
+
Binary
|
26
|
+
URL
|
27
|
+
Email
|
28
|
+
IPAddress
|
29
|
+
JSON
|
30
|
+
Enum).each do |t|
|
31
|
+
class_eval <<~HEREDOC
|
32
|
+
class #{t}
|
33
|
+
def self.cast(value)
|
34
|
+
Type.cast(value, #{t})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
HEREDOC
|
39
|
+
end
|
40
|
+
|
41
|
+
class TimeWithoutDate
|
42
|
+
def self.cast(value)
|
43
|
+
parsed_time = ::Time.parse(value.to_s)
|
44
|
+
parsed_time.strftime("%H:%M:%S")
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.serialize(value)
|
48
|
+
value.strftime("%H:%M:%S")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class DateTime
|
53
|
+
def self.cast(value)
|
54
|
+
::DateTime.parse(value.to_s).new_offset(0).iso8601
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.cast(value, type)
|
59
|
+
case type
|
60
|
+
when String
|
61
|
+
value.to_s
|
62
|
+
when Integer
|
63
|
+
value.to_i
|
64
|
+
when Float
|
65
|
+
value.to_f
|
66
|
+
when Date
|
67
|
+
begin
|
68
|
+
::Date.parse(value.to_s)
|
69
|
+
rescue ArgumentError
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
when DateTime
|
73
|
+
DateTime.cast(value)
|
74
|
+
when Time
|
75
|
+
::Time.parse(value.to_s)
|
76
|
+
when TimeWithoutDate
|
77
|
+
TimeWithoutDate.cast(value)
|
78
|
+
when Boolean
|
79
|
+
to_boolean(value)
|
80
|
+
when Decimal
|
81
|
+
BigDecimal(value.to_s)
|
82
|
+
when Hash
|
83
|
+
Hash(value)
|
84
|
+
when UUID
|
85
|
+
value =~ /\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/ ? value : SecureRandom.uuid
|
86
|
+
when Symbol
|
87
|
+
value.to_sym
|
88
|
+
when BigInteger
|
89
|
+
value.to_i
|
90
|
+
when Binary
|
91
|
+
value.force_encoding("BINARY")
|
92
|
+
when URL
|
93
|
+
URI.parse(value.to_s)
|
94
|
+
when Email
|
95
|
+
value.to_s
|
96
|
+
when IPAddress
|
97
|
+
IPAddr.new(value.to_s)
|
98
|
+
when JSON
|
99
|
+
::JSON.parse(value)
|
100
|
+
when Enum
|
101
|
+
value
|
102
|
+
else
|
103
|
+
value
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.to_boolean(value)
|
108
|
+
return true if value == true || value.to_s =~ (/^(true|t|yes|y|1)$/i)
|
109
|
+
return false if value == false || value.nil? || value.to_s =~ (/^(false|f|no|n|0)$/i)
|
110
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{value}\"")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# lib/lutaml/model/xml_adapter/nokogiri_adapter.rb
|
2
|
+
require "nokogiri"
|
3
|
+
require_relative "../xml_adapter"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module XmlAdapter
|
8
|
+
class NokogiriDocument < Document
|
9
|
+
def self.parse(xml)
|
10
|
+
parsed = Nokogiri::XML(xml)
|
11
|
+
root = NokogiriElement.new(parsed.root)
|
12
|
+
new(root)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(root)
|
16
|
+
@root = root
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{ @root.name => parse_element(@root) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml(options = {})
|
24
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
25
|
+
build_element(xml, @root, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
xml_data = builder.to_xml(options[:pretty] ? { indent: 2 } : {})
|
29
|
+
options[:declaration] ? declaration(options) + xml_data : xml_data
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def build_element(xml, element, options = {})
|
35
|
+
xml_mapping = element.class.mappings_for(:xml)
|
36
|
+
return xml unless xml_mapping
|
37
|
+
|
38
|
+
attributes = build_attributes(element, xml_mapping)
|
39
|
+
|
40
|
+
xml.send(xml_mapping.root_element, attributes) do
|
41
|
+
xml_mapping.elements.each do |element_rule|
|
42
|
+
attribute_def = element.class.attributes[element_rule.to]
|
43
|
+
value = element.send(element_rule.to)
|
44
|
+
|
45
|
+
if attribute_def&.type <= Lutaml::Model::Serialize
|
46
|
+
handle_nested_elements(xml, element_rule, value)
|
47
|
+
else
|
48
|
+
xml.send(element_rule.name) { xml.text value }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
xml.text element.text unless xml_mapping.elements.any?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_attributes(element, xml_mapping)
|
56
|
+
xml_mapping.attributes.each_with_object(namespace_attributes(xml_mapping)) do |mapping_rule, hash|
|
57
|
+
full_name = if mapping_rule.namespace
|
58
|
+
"#{mapping_rule.prefix ? "#{mapping_rule.prefix}:" : ""}#{mapping_rule.name}"
|
59
|
+
else
|
60
|
+
mapping_rule.name
|
61
|
+
end
|
62
|
+
hash[full_name] = element.send(mapping_rule.to)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def namespace_attributes(xml_mapping)
|
67
|
+
return {} unless xml_mapping.namespace_uri
|
68
|
+
|
69
|
+
if xml_mapping.namespace_prefix
|
70
|
+
{ "xmlns:#{xml_mapping.namespace_prefix}" => xml_mapping.namespace_uri }
|
71
|
+
else
|
72
|
+
{ "xmlns" => xml_mapping.namespace_uri }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def handle_nested_elements(xml, element_rule, value)
|
77
|
+
case value
|
78
|
+
when Array
|
79
|
+
value.each { |val| build_element(xml, val) }
|
80
|
+
else
|
81
|
+
build_element(xml, value)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_element(element)
|
86
|
+
result = element.children.each_with_object({}) do |child, hash|
|
87
|
+
next if child.text?
|
88
|
+
|
89
|
+
hash[child.name] ||= []
|
90
|
+
hash[child.name] << parse_element(child)
|
91
|
+
end
|
92
|
+
result["_text"] = element.text if element.text?
|
93
|
+
result
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class NokogiriElement < Element
|
98
|
+
def initialize(node)
|
99
|
+
attributes = node.attributes.transform_values do |attr|
|
100
|
+
Attribute.new(attr.name, attr.value, namespace: attr.namespace&.href, namespace_prefix: attr.namespace&.prefix)
|
101
|
+
end
|
102
|
+
super(node.name, attributes, parse_children(node), node.text, namespace: node.namespace&.href, namespace_prefix: node.namespace&.prefix)
|
103
|
+
end
|
104
|
+
|
105
|
+
def text?
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def parse_children(node)
|
112
|
+
node.children.select(&:element?).map { |child| NokogiriElement.new(child) }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# lib/lutaml/model/xml_adapter/oga_adapter.rb
|
2
|
+
require "oga"
|
3
|
+
require_relative "../xml_adapter"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module XmlAdapter
|
8
|
+
class OgaDocument < Document
|
9
|
+
def self.parse(xml)
|
10
|
+
parsed = Oga.parse_xml(xml)
|
11
|
+
root = OgaElement.new(parsed)
|
12
|
+
new(root)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(root)
|
16
|
+
@root = root
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{ @root.name => parse_element(@root) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml(options = {})
|
24
|
+
builder = Oga::XML::Builder.new
|
25
|
+
build_element(builder, @root, options)
|
26
|
+
xml_data = builder.to_xml
|
27
|
+
options[:declaration] ? declaration(options) + xml_data : xml_data
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def build_element(builder, element, options = {})
|
33
|
+
attributes = build_attributes(element.attributes)
|
34
|
+
builder.element(element.name, attributes) do
|
35
|
+
element.children.each do |child|
|
36
|
+
build_element(builder, child, options)
|
37
|
+
end
|
38
|
+
builder.text(element.text) if element.text
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_attributes(attributes)
|
43
|
+
attributes.each_with_object({}) do |(name, attr), hash|
|
44
|
+
hash[name] = attr.value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_element(element)
|
49
|
+
result = { "_text" => element.text }
|
50
|
+
element.children.each do |child|
|
51
|
+
next if child.is_a?(Oga::XML::Text)
|
52
|
+
result[child.name] ||= []
|
53
|
+
result[child.name] << parse_element(child)
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class OgaElement < Element
|
60
|
+
def initialize(node)
|
61
|
+
attributes = node.attributes.each_with_object({}) do |attr, hash|
|
62
|
+
hash[attr.name] = Attribute.new(attr.name, attr.value)
|
63
|
+
end
|
64
|
+
super(node.name, attributes, parse_children(node), node.text)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def parse_children(node)
|
70
|
+
node.children.select { |child| child.is_a?(Oga::XML::Element) }.map { |child| OgaElement.new(child) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# lib/lutaml/model/xml_adapter/ox_adapter.rb
|
2
|
+
require "ox"
|
3
|
+
require_relative "../xml_adapter"
|
4
|
+
|
5
|
+
module Lutaml
|
6
|
+
module Model
|
7
|
+
module XmlAdapter
|
8
|
+
class OxDocument < Document
|
9
|
+
def self.parse(xml)
|
10
|
+
parsed = Ox.parse(xml)
|
11
|
+
root = OxElement.new(parsed)
|
12
|
+
new(root)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(root)
|
16
|
+
@root = root
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{ @root.name => parse_element(@root) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_xml(options = {})
|
24
|
+
builder = Ox::Builder.new
|
25
|
+
build_element(builder, @root, options)
|
26
|
+
xml_data = Ox.dump(builder)
|
27
|
+
options[:declaration] ? declaration(options) + xml_data : xml_data
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def build_element(builder, element, options = {})
|
33
|
+
attributes = build_attributes(element.attributes)
|
34
|
+
builder.element(element.name, attributes) do
|
35
|
+
element.children.each do |child|
|
36
|
+
build_element(builder, child, options)
|
37
|
+
end
|
38
|
+
builder.text(element.text) if element.text
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build_attributes(attributes)
|
43
|
+
attributes.each_with_object({}) do |(name, attr), hash|
|
44
|
+
hash[name] = attr.value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_element(element)
|
49
|
+
result = { "_text" => element.text }
|
50
|
+
element.nodes.each do |child|
|
51
|
+
next if child.is_a?(Ox::Raw) || child.is_a?(Ox::Comment)
|
52
|
+
result[child.name] ||= []
|
53
|
+
result[child.name] << parse_element(child)
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class OxElement < Element
|
60
|
+
def initialize(node)
|
61
|
+
attributes = node.attributes.each_with_object({}) do |(name, value), hash|
|
62
|
+
hash[name.to_s] = Attribute.new(name.to_s, value)
|
63
|
+
end
|
64
|
+
super(node.name.to_s, attributes, parse_children(node), node.text)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def parse_children(node)
|
70
|
+
node.nodes.select { |child| child.is_a?(Ox::Element) }.map { |child| OxElement.new(child) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# lib/lutaml/model/xml_adapter.rb
|
2
|
+
|
3
|
+
module Lutaml
|
4
|
+
module Model
|
5
|
+
module XmlAdapter
|
6
|
+
class Document
|
7
|
+
attr_reader :root
|
8
|
+
|
9
|
+
def initialize(root)
|
10
|
+
@root = root
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse(xml)
|
14
|
+
raise NotImplementedError, "Subclasses must implement `parse`."
|
15
|
+
end
|
16
|
+
|
17
|
+
def children
|
18
|
+
@root.children
|
19
|
+
end
|
20
|
+
|
21
|
+
def declaration(options)
|
22
|
+
version = options[:declaration].is_a?(String) ? options[:declaration] : "1.0"
|
23
|
+
encoding = options[:encoding].is_a?(String) ? options[:encoding] : (options[:encoding] ? "UTF-8" : nil)
|
24
|
+
declaration = "<?xml version=\"#{version}\""
|
25
|
+
declaration += " encoding=\"#{encoding}\"" if encoding
|
26
|
+
declaration += "?>\n"
|
27
|
+
declaration
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Element
|
32
|
+
attr_reader :name, :attributes, :children, :text, :namespace, :namespace_prefix
|
33
|
+
|
34
|
+
def initialize(name, attributes = {}, children = [], text = nil, namespace: nil, namespace_prefix: nil)
|
35
|
+
@name = name
|
36
|
+
@attributes = attributes.map { |k, v| Attribute.new(k, v) }
|
37
|
+
@children = children
|
38
|
+
@text = text
|
39
|
+
@namespace = namespace
|
40
|
+
@namespace_prefix = namespace_prefix
|
41
|
+
end
|
42
|
+
|
43
|
+
def document
|
44
|
+
Document.new(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Attribute
|
49
|
+
attr_reader :name, :value, :namespace, :namespace_prefix
|
50
|
+
|
51
|
+
def initialize(name, value, namespace: nil, namespace_prefix: nil)
|
52
|
+
@name = name
|
53
|
+
@value = value
|
54
|
+
@namespace = namespace
|
55
|
+
@namespace_prefix = namespace_prefix
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# lib/lutaml/model/xml_mapping.rb
|
2
|
+
require_relative "xml_mapping_rule"
|
3
|
+
|
4
|
+
module Lutaml
|
5
|
+
module Model
|
6
|
+
class XmlMapping
|
7
|
+
attr_reader :root_element, :namespace_uri, :namespace_prefix
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@elements = []
|
11
|
+
@attributes = []
|
12
|
+
@content_mapping = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def root(name)
|
16
|
+
@root_element = name
|
17
|
+
end
|
18
|
+
|
19
|
+
def namespace(uri, prefix = nil)
|
20
|
+
@namespace_uri = uri
|
21
|
+
@namespace_prefix = prefix
|
22
|
+
end
|
23
|
+
|
24
|
+
def map_element(name, to:, render_nil: false, with: {}, delegate: nil, namespace: nil, prefix: nil)
|
25
|
+
@elements << XmlMappingRule.new(name, to: to, render_nil: render_nil, with: with, delegate: delegate, namespace: namespace, prefix: prefix)
|
26
|
+
end
|
27
|
+
|
28
|
+
def map_attribute(name, to:, render_nil: false, with: {}, delegate: nil, namespace: nil, prefix: nil)
|
29
|
+
@attributes << XmlMappingRule.new(name, to: to, render_nil: render_nil, with: with, delegate: delegate, namespace: namespace, prefix: prefix)
|
30
|
+
end
|
31
|
+
|
32
|
+
def map_content(to:, render_nil: false, with: {}, delegate: nil)
|
33
|
+
@content_mapping = XmlMappingRule.new(nil, to: to, render_nil: render_nil, with: with, delegate: delegate)
|
34
|
+
end
|
35
|
+
|
36
|
+
def elements
|
37
|
+
@elements
|
38
|
+
end
|
39
|
+
|
40
|
+
def attributes
|
41
|
+
@attributes
|
42
|
+
end
|
43
|
+
|
44
|
+
def content_mapping
|
45
|
+
@content_mapping
|
46
|
+
end
|
47
|
+
|
48
|
+
def mappings
|
49
|
+
elements + attributes + [content_mapping].compact
|
50
|
+
end
|
51
|
+
|
52
|
+
def element(name)
|
53
|
+
elements.detect do |rule|
|
54
|
+
name == rule.to
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def attribute(name)
|
59
|
+
attributes.detect do |rule|
|
60
|
+
name == rule.to
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# lib/lutaml/model/xml_mapping_rule.rb
|
2
|
+
require_relative "mapping_rule"
|
3
|
+
|
4
|
+
module Lutaml
|
5
|
+
module Model
|
6
|
+
class XmlMappingRule < MappingRule
|
7
|
+
attr_reader :namespace, :prefix
|
8
|
+
|
9
|
+
def initialize(name, to:, render_nil: false, with: {}, delegate: nil, namespace: nil, prefix: nil)
|
10
|
+
super(name, to: to, render_nil: render_nil, with: with, delegate: delegate)
|
11
|
+
@namespace = namespace
|
12
|
+
@prefix = prefix
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# lib/lutaml/model/yaml_adapter.rb
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module Lutaml
|
5
|
+
module Model
|
6
|
+
module YamlAdapter
|
7
|
+
module Standard
|
8
|
+
def self.to_yaml(model, *args)
|
9
|
+
YAML.dump(model.hash_representation(:yaml), *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_yaml(yaml, klass)
|
13
|
+
data = parse(yaml)
|
14
|
+
mapped_attrs = klass.send(:apply_mappings, data, :yaml)
|
15
|
+
klass.new(mapped_attrs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse(yaml)
|
19
|
+
YAML.safe_load(yaml, permitted_classes: [Date, Time, DateTime, Symbol, BigDecimal, Hash, Array])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/lutaml/model.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "model/version"
|
4
|
+
|
5
|
+
# lib/lutaml/model.rb
|
6
|
+
require "nokogiri"
|
7
|
+
require "json"
|
8
|
+
require "yaml"
|
9
|
+
require_relative "model/type"
|
10
|
+
require_relative "model/serializable"
|
11
|
+
require_relative "model/json_adapter"
|
12
|
+
require_relative "model/yaml_adapter"
|
13
|
+
require_relative "model/xml_adapter"
|
14
|
+
require_relative "model/toml_adapter"
|
15
|
+
|
16
|
+
module Lutaml
|
17
|
+
module Model
|
18
|
+
class BaseModel < Serializable
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/lutaml/model/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "lutaml-model"
|
7
|
+
spec.version = Lutaml::Model::VERSION
|
8
|
+
spec.authors = ["Ribose Inc."]
|
9
|
+
spec.email = ["open.source@ribose.com"]
|
10
|
+
|
11
|
+
spec.summary = "LutaML creating data models in Ruby"
|
12
|
+
spec.description = <<~DESCRIPTION
|
13
|
+
LutaML creating data models in Ruby
|
14
|
+
DESCRIPTION
|
15
|
+
|
16
|
+
spec.homepage = "https://github.com/lutaml/lutaml-model"
|
17
|
+
spec.license = "BSD-2-Clause"
|
18
|
+
|
19
|
+
spec.bindir = "bin"
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
spec.files = `git ls-files`.split("\n")
|
22
|
+
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
|
23
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
24
|
+
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
26
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
29
|
+
f.match(%r{^(test|spec|features)/})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
spec.bindir = "exe"
|
33
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ["lib"]
|
35
|
+
|
36
|
+
# spec.add_runtime_dependency "expressir"
|
37
|
+
# spec.add_runtime_dependency "metanorma-cli"
|
38
|
+
# spec.add_runtime_dependency "shale"
|
39
|
+
# spec.add_runtime_dependency "thor", ">= 0.20"
|
40
|
+
spec.add_development_dependency "multi_json"
|
41
|
+
spec.add_development_dependency "tomlib"
|
42
|
+
spec.add_development_dependency "toml-rb"
|
43
|
+
spec.add_development_dependency "oga"
|
44
|
+
spec.add_development_dependency "ox"
|
45
|
+
spec.add_development_dependency "nokogiri"
|
46
|
+
spec.add_development_dependency "rubocop"
|
47
|
+
spec.add_development_dependency "rubocop-performance"
|
48
|
+
spec.add_development_dependency "rubocop-rails"
|
49
|
+
spec.add_development_dependency "equivalent-xml"
|
50
|
+
end
|