edoxen 0.1.1 → 0.3.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 +4 -4
- data/.rubocop_todo.yml +202 -40
- data/CLAUDE.md +220 -0
- data/README.adoc +150 -206
- data/edoxen.gemspec +7 -1
- data/exe/edoxen +6 -0
- data/lib/edoxen/_metadata.rb.deprecated +57 -0
- data/lib/edoxen/action.rb +4 -52
- data/lib/edoxen/approval.rb +5 -25
- data/lib/edoxen/cli.rb +156 -0
- data/lib/edoxen/consideration.rb +5 -36
- data/lib/edoxen/enums.rb +43 -0
- data/lib/edoxen/error.rb +7 -0
- data/lib/edoxen/localization.rb +30 -0
- data/lib/edoxen/{meeting_identfier.rb → meeting_identifier.rb} +2 -6
- data/lib/edoxen/resolution.rb +24 -51
- data/lib/edoxen/resolution_collection.rb +3 -13
- data/lib/edoxen/resolution_date.rb +13 -30
- data/lib/edoxen/resolution_metadata.rb +26 -0
- data/lib/edoxen/resolution_relation.rb +17 -0
- data/lib/edoxen/resolution_set.rb +17 -0
- data/lib/edoxen/schema_validator.rb +211 -0
- data/lib/edoxen/source_url.rb +18 -0
- data/lib/edoxen/structured_identifier.rb +6 -9
- data/lib/edoxen/url.rb +16 -0
- data/lib/edoxen/version.rb +1 -1
- data/lib/edoxen.rb +36 -18
- data/schema/edoxen.yaml +308 -212
- metadata +52 -13
- data/lib/edoxen/resolution_relationship.rb +0 -51
- data/lib/edoxen/subject_body.rb +0 -20
data/lib/edoxen/cli.rb
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
module Edoxen
|
|
7
|
+
# Thor command-line surface for the gem. Two responsibilities:
|
|
8
|
+
# * `validate PATTERN` — runs both JSON-Schema validation and the
|
|
9
|
+
# Ruby model parser against each matching YAML file.
|
|
10
|
+
# * `normalize PATTERN (--output DIR | --inplace)` — round-trips each
|
|
11
|
+
# matching YAML file through the Ruby model, preserving any
|
|
12
|
+
# `# yaml-language-server: $schema=...` directive on the first line.
|
|
13
|
+
#
|
|
14
|
+
# The CLI deliberately does NOT own schema-or-model decisions — those
|
|
15
|
+
# live in `SchemaValidator` and `Lutaml::Model` respectively. It only
|
|
16
|
+
# glues them together and formats output.
|
|
17
|
+
class Cli < Thor
|
|
18
|
+
package_name "edoxen"
|
|
19
|
+
|
|
20
|
+
desc "validate YAML_FILE_PATTERN",
|
|
21
|
+
"Validate one or more Edoxen YAML files against the schema and the model."
|
|
22
|
+
|
|
23
|
+
def validate(pattern)
|
|
24
|
+
files = expand_yaml_pattern(pattern)
|
|
25
|
+
if files.empty?
|
|
26
|
+
say "No files found matching pattern: #{pattern}", :red
|
|
27
|
+
exit 1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
say "🔍 Validating #{files.size} file(s)...", :blue
|
|
31
|
+
|
|
32
|
+
validator = SchemaValidator.new
|
|
33
|
+
valid_count = 0
|
|
34
|
+
invalid_count = 0
|
|
35
|
+
|
|
36
|
+
files.each do |file|
|
|
37
|
+
print " #{File.basename(file)}... "
|
|
38
|
+
|
|
39
|
+
schema_errors = validator.validate_file(file)
|
|
40
|
+
model_errors = collect_model_errors(file)
|
|
41
|
+
|
|
42
|
+
if schema_errors.empty? && model_errors.empty?
|
|
43
|
+
say "✅ VALID", :green
|
|
44
|
+
valid_count += 1
|
|
45
|
+
else
|
|
46
|
+
say "❌ INVALID", :red
|
|
47
|
+
invalid_count += 1
|
|
48
|
+
schema_errors.each { |e| say " #{e.to_clickable_format}", :red }
|
|
49
|
+
model_errors.each { |m| say " #{file}:1:1: #{m}", :red }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
print_summary(files.size, valid_count, invalid_count, validator_type: :binary)
|
|
54
|
+
exit(invalid_count.positive? ? 1 : 0)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc "normalize YAML_FILE_PATTERN",
|
|
58
|
+
"Round-trip YAML file(s) through the Edoxen model (--output DIR or --inplace)."
|
|
59
|
+
|
|
60
|
+
option :output, type: :string, desc: "Output directory for normalized files"
|
|
61
|
+
option :inplace, type: :boolean, desc: "Modify files in place (no backup)"
|
|
62
|
+
|
|
63
|
+
def normalize(pattern)
|
|
64
|
+
if options[:output] && options[:inplace]
|
|
65
|
+
say "Error: Cannot use both --output and --inplace options", :red
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
unless options[:output] || options[:inplace]
|
|
70
|
+
say "Error: Must specify either --output or --inplace option", :red
|
|
71
|
+
exit 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
files = expand_yaml_pattern(pattern)
|
|
75
|
+
if files.empty?
|
|
76
|
+
say "No files found matching pattern: #{pattern}", :red
|
|
77
|
+
exit 1
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
say "🔄 Normalizing #{files.size} file(s)...", :blue
|
|
81
|
+
|
|
82
|
+
success_count = 0
|
|
83
|
+
error_count = 0
|
|
84
|
+
|
|
85
|
+
files.each do |file|
|
|
86
|
+
print " #{File.basename(file)}... "
|
|
87
|
+
begin
|
|
88
|
+
yaml_language_server_comment = extract_yaml_language_server_comment(File.read(file))
|
|
89
|
+
normalized = ResolutionCollection.from_yaml(File.read(file)).to_yaml
|
|
90
|
+
normalized = "#{yaml_language_server_comment}\n#{normalized}" if yaml_language_server_comment
|
|
91
|
+
|
|
92
|
+
if options[:inplace]
|
|
93
|
+
File.write(file, normalized)
|
|
94
|
+
say "✅ NORMALIZED", :green
|
|
95
|
+
else
|
|
96
|
+
out = File.join(options[:output], File.basename(file))
|
|
97
|
+
FileUtils.mkdir_p(File.dirname(out))
|
|
98
|
+
File.write(out, normalized)
|
|
99
|
+
say "✅ NORMALIZED → #{out}", :green
|
|
100
|
+
end
|
|
101
|
+
success_count += 1
|
|
102
|
+
rescue StandardError => e
|
|
103
|
+
say "❌ FAILED — #{e.message}", :red
|
|
104
|
+
error_count += 1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
print_summary(files.size, success_count, error_count, validator_type: :lax,
|
|
109
|
+
extra: [
|
|
110
|
+
[" Output directory", options[:output]],
|
|
111
|
+
[" Mode", options[:inplace] ? "in place" : "--output"]
|
|
112
|
+
].compact)
|
|
113
|
+
exit(error_count.positive? ? 1 : 0)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
no_commands do
|
|
117
|
+
# Reserved for private Thor plumbing if we add it later.
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def expand_yaml_pattern(pattern)
|
|
123
|
+
Dir.glob(pattern).select { |f| File.file?(f) && f.match?(/\.ya?ml\z/i) }.sort
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Round-trip the file through the model to catch structural issues
|
|
127
|
+
# (missing nested classes, type mismatches) that the JSON-Schema can't
|
|
128
|
+
# express. The model is permissive about field names — schema is the
|
|
129
|
+
# strict source.
|
|
130
|
+
def collect_model_errors(file)
|
|
131
|
+
ResolutionCollection.from_yaml(File.read(file))
|
|
132
|
+
[]
|
|
133
|
+
rescue StandardError => e
|
|
134
|
+
["Model parsing failed: #{e.message}"]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def extract_yaml_language_server_comment(content)
|
|
138
|
+
lines = content.split("\n").first(5)
|
|
139
|
+
lines.find { |l| l.strip.match?(/\A#\s*yaml-language-server:\s*\$schema=/) }&.rstrip
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def print_summary(total, ok_count, bad_count, validator_type:, extra: [])
|
|
143
|
+
say "\n📊 Summary:", :blue
|
|
144
|
+
say " Total: #{total}", :blue
|
|
145
|
+
label_text = if validator_type == :binary
|
|
146
|
+
" Valid: #{ok_count}, Invalid: #{bad_count}"
|
|
147
|
+
else
|
|
148
|
+
" Success: #{ok_count}, Failed: #{bad_count}"
|
|
149
|
+
end
|
|
150
|
+
say label_text, bad_count.positive? ? :red : :green
|
|
151
|
+
success_rate = total.zero? ? 0 : ((ok_count.to_f / total) * 100).round(1)
|
|
152
|
+
say " Success rate: #{success_rate}%", :blue
|
|
153
|
+
extra.each { |label, value| say " #{label}: #{value}", :blue }
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
data/lib/edoxen/consideration.rb
CHANGED
|
@@ -1,47 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Consideration {
|
|
4
|
-
# type: ConsiderationType
|
|
5
|
-
# dateEffective: Date
|
|
6
|
-
# message: Text
|
|
7
|
-
# }
|
|
8
|
-
|
|
9
|
-
# enum ConsiderationType {
|
|
10
|
-
# having / having regard
|
|
11
|
-
# noting
|
|
12
|
-
# recognizing
|
|
13
|
-
# acknowledging
|
|
14
|
-
# recalling / further recalling
|
|
15
|
-
# reaffirming
|
|
16
|
-
# considering
|
|
17
|
-
# taking into account
|
|
18
|
-
# pursuant to
|
|
19
|
-
# bearing in mind
|
|
20
|
-
# emphasizing
|
|
21
|
-
# concerned
|
|
22
|
-
# accepts
|
|
23
|
-
# observing
|
|
24
|
-
# referring
|
|
25
|
-
# acting
|
|
26
|
-
# empowers
|
|
27
|
-
# reaffirming
|
|
28
|
-
# }
|
|
29
|
-
|
|
30
|
-
require "lutaml/model"
|
|
31
|
-
|
|
32
3
|
module Edoxen
|
|
4
|
+
# Basis for a resolution: a verb (having, noting, considering, ...) plus
|
|
5
|
+
# one effective date and the elaborated reasoning.
|
|
33
6
|
class Consideration < Lutaml::Model::Serializable
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
referring acting empowers reaffirming].freeze
|
|
37
|
-
|
|
38
|
-
attribute :type, :string, values: CONSIDERATION_TYPE_ENUM
|
|
39
|
-
attribute :date, :date
|
|
7
|
+
attribute :type, :string, values: Enums::CONSIDERATION_TYPE
|
|
8
|
+
attribute :date_effective, ResolutionDate
|
|
40
9
|
attribute :message, :string
|
|
41
10
|
|
|
42
11
|
key_value do
|
|
43
12
|
map "type", to: :type
|
|
44
|
-
map "
|
|
13
|
+
map "date_effective", to: :date_effective
|
|
45
14
|
map "message", to: :message
|
|
46
15
|
end
|
|
47
16
|
end
|
data/lib/edoxen/enums.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edoxen
|
|
4
|
+
# Single source of truth for every enum used by the Edoxen information model.
|
|
5
|
+
#
|
|
6
|
+
# Mirrors ../edoxen-model/models/*.lutaml, deduped.
|
|
7
|
+
# Both:
|
|
8
|
+
# * Ruby model attribute declarations (`attribute :type, :string, values: Enums::ACTION_TYPE`)
|
|
9
|
+
# * JSON-Schema (`schema/edoxen.yaml`)
|
|
10
|
+
# reference these constants.
|
|
11
|
+
#
|
|
12
|
+
# The schema <-> Ruby enum-sync spec asserts the YAML schema's enum arrays
|
|
13
|
+
# equal these arrays. If you change a constant here, change the schema in
|
|
14
|
+
# the same PR.
|
|
15
|
+
module Enums
|
|
16
|
+
ACTION_TYPE = %w[
|
|
17
|
+
adopts thanks approves decides declares asks invites
|
|
18
|
+
resolves confirms welcomes recommends requests congratulates
|
|
19
|
+
instructs urges appoints calls-upon encourages affirms elects
|
|
20
|
+
authorizes charges states remarks judges sanctions abrogates empowers
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
CONSIDERATION_TYPE = %w[
|
|
24
|
+
having noting recognizing acknowledging recalling reaffirming
|
|
25
|
+
considering taking-into-account pursuant-to bearing-in-mind
|
|
26
|
+
emphasizing concerned accepts observing referring acting empowers
|
|
27
|
+
].freeze
|
|
28
|
+
|
|
29
|
+
RESOLUTION_TYPE = %w[resolution recommendation decision declaration].freeze
|
|
30
|
+
|
|
31
|
+
RESOLUTION_RELATION_TYPE = %w[
|
|
32
|
+
annexOf hasAnnex updates refines replaces considers
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
35
|
+
RESOLUTION_DATE_TYPE = %w[adoption drafted discussed].freeze
|
|
36
|
+
|
|
37
|
+
APPROVAL_TYPE = %w[affirmative negative].freeze
|
|
38
|
+
|
|
39
|
+
APPROVAL_DEGREE = %w[unanimous majority minority].freeze
|
|
40
|
+
|
|
41
|
+
URL_KIND = %w[access report].freeze
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/edoxen/error.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edoxen
|
|
4
|
+
# A monolingual rendering of a Resolution. Mirrors the glossarist
|
|
5
|
+
# LocalizedConcept pattern: language-agnostic fields live on the
|
|
6
|
+
# parent Resolution; per-language content lives here.
|
|
7
|
+
class Localization < Lutaml::Model::Serializable
|
|
8
|
+
attribute :language_code, :string
|
|
9
|
+
attribute :script, :string
|
|
10
|
+
attribute :title, :string
|
|
11
|
+
attribute :subject, :string
|
|
12
|
+
attribute :message, :string
|
|
13
|
+
attribute :considering, :string
|
|
14
|
+
attribute :considerations, Consideration, collection: true
|
|
15
|
+
attribute :approvals, Approval, collection: true
|
|
16
|
+
attribute :actions, Action, collection: true
|
|
17
|
+
|
|
18
|
+
key_value do
|
|
19
|
+
map "language_code", to: :language_code
|
|
20
|
+
map "script", to: :script
|
|
21
|
+
map "title", to: :title
|
|
22
|
+
map "subject", to: :subject
|
|
23
|
+
map "message", to: :message
|
|
24
|
+
map "considering", to: :considering
|
|
25
|
+
map "considerations", to: :considerations
|
|
26
|
+
map "approvals", to: :approvals
|
|
27
|
+
map "actions", to: :actions
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# MeetingIdentifier {
|
|
4
|
-
# venue: String
|
|
5
|
-
# date: DateTime
|
|
6
|
-
# }
|
|
7
|
-
require "lutaml/model"
|
|
8
|
-
|
|
9
3
|
module Edoxen
|
|
4
|
+
# Identifier of a meeting (venue + date). Singular — the meeting a
|
|
5
|
+
# particular Resolution belongs to.
|
|
10
6
|
class MeetingIdentifier < Lutaml::Model::Serializable
|
|
11
7
|
attribute :venue, :string
|
|
12
8
|
attribute :date, :date
|
data/lib/edoxen/resolution.rb
CHANGED
|
@@ -1,61 +1,34 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
|
|
5
3
|
module Edoxen
|
|
4
|
+
# A formal Resolution. Language-agnostic admin fields live here; every
|
|
5
|
+
# translatable field is wrapped inside `localizations[]` (one entry per
|
|
6
|
+
# available language; at least one is required by the schema).
|
|
6
7
|
class Resolution < Lutaml::Model::Serializable
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
attribute :
|
|
10
|
-
attribute :
|
|
11
|
-
attribute :
|
|
12
|
-
attribute :
|
|
13
|
-
attribute :
|
|
14
|
-
attribute :
|
|
15
|
-
attribute :
|
|
16
|
-
attribute :
|
|
17
|
-
attribute :
|
|
8
|
+
attribute :identifier, StructuredIdentifier, collection: true
|
|
9
|
+
attribute :type, :string, values: Enums::RESOLUTION_TYPE
|
|
10
|
+
attribute :doi, :string
|
|
11
|
+
attribute :urn, :string
|
|
12
|
+
attribute :agenda_item, :string
|
|
13
|
+
attribute :dates, ResolutionDate, collection: true
|
|
14
|
+
attribute :categories, :string, collection: true
|
|
15
|
+
attribute :meeting, MeetingIdentifier
|
|
16
|
+
attribute :relations, ResolutionRelation, collection: true
|
|
17
|
+
attribute :urls, Url, collection: true
|
|
18
|
+
attribute :localizations, Localization, collection: true
|
|
18
19
|
|
|
19
20
|
key_value do
|
|
20
|
-
map "category", to: :category
|
|
21
|
-
map "dates", to: :dates
|
|
22
|
-
map "subject", to: :subject
|
|
23
|
-
map "title", to: :title
|
|
24
|
-
map "type", to: :type
|
|
25
21
|
map "identifier", to: :identifier
|
|
26
|
-
map "
|
|
27
|
-
map "
|
|
28
|
-
map "
|
|
22
|
+
map "type", to: :type
|
|
23
|
+
map "doi", to: :doi
|
|
24
|
+
map "urn", to: :urn
|
|
25
|
+
map "agenda_item", to: :agenda_item
|
|
26
|
+
map "dates", to: :dates
|
|
27
|
+
map "categories", to: :categories
|
|
28
|
+
map "meeting", to: :meeting
|
|
29
|
+
map "relations", to: :relations
|
|
30
|
+
map "urls", to: :urls
|
|
31
|
+
map "localizations", to: :localizations
|
|
29
32
|
end
|
|
30
|
-
|
|
31
|
-
# Example of a Resolution
|
|
32
|
-
# category: Resolutions related to JWG 1
|
|
33
|
-
# dates:
|
|
34
|
-
# - 2019-10-17
|
|
35
|
-
# subject: ISO/TC 154
|
|
36
|
-
# title: "Adoption of NWIP ballot for ISO/PWI 9735-11 "Electronic data..."
|
|
37
|
-
# identifier: 2019-01
|
|
38
|
-
# considerations:
|
|
39
|
-
# - type: considering
|
|
40
|
-
# date_effective: 2019-10-17
|
|
41
|
-
# message: considering the voting result ...
|
|
42
|
-
|
|
43
|
-
# - type: considering
|
|
44
|
-
# date_effective: 2019-10-17
|
|
45
|
-
# message: considering the importance of ...
|
|
46
|
-
|
|
47
|
-
# - type: considering
|
|
48
|
-
# date_effective: 2019-10-17
|
|
49
|
-
# message: considering the request from JWG1...
|
|
50
|
-
|
|
51
|
-
# approvals:
|
|
52
|
-
# - type: affirmative
|
|
53
|
-
# degree: unanimous
|
|
54
|
-
# message: The resolution was taken by unanimity.
|
|
55
|
-
|
|
56
|
-
# actions:
|
|
57
|
-
# - type: resolves
|
|
58
|
-
# date_effective: 2019-10-17
|
|
59
|
-
# message: resolves to submit ISO 9735-11...
|
|
60
33
|
end
|
|
61
34
|
end
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
|
|
5
3
|
module Edoxen
|
|
4
|
+
# Top-level container for a published resolution collection: metadata
|
|
5
|
+
# plus the list of resolutions.
|
|
6
6
|
class ResolutionCollection < Lutaml::Model::Serializable
|
|
7
|
-
attribute :metadata,
|
|
7
|
+
attribute :metadata, ResolutionMetadata
|
|
8
8
|
attribute :resolutions, Resolution, collection: true
|
|
9
9
|
|
|
10
10
|
key_value do
|
|
11
11
|
map "metadata", to: :metadata
|
|
12
12
|
map "resolutions", to: :resolutions
|
|
13
13
|
end
|
|
14
|
-
|
|
15
|
-
# Example of a ResolutionCollection
|
|
16
|
-
# metadata:
|
|
17
|
-
# title: Resolutions of the 38th plenary meeting of ISO/TC 154
|
|
18
|
-
# date: 2019-10-17
|
|
19
|
-
# source: ISO/TC 154 Secretariat
|
|
20
|
-
# resolutions:
|
|
21
|
-
# - category: Resolutions related to JWG 1
|
|
22
|
-
# dates: 2019/10/17
|
|
23
|
-
# ...
|
|
24
14
|
end
|
|
25
15
|
end
|
|
@@ -1,33 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
|
|
3
|
+
module Edoxen
|
|
4
|
+
# Date with semantic kind (adoption, drafted, discussed).
|
|
5
|
+
# ResolutionDate is the only carrier of a *typed* date in the model —
|
|
6
|
+
# plain `Date` in lutaml-model has no semantic context.
|
|
7
|
+
class ResolutionDate < Lutaml::Model::Serializable
|
|
8
|
+
attribute :date, :date
|
|
9
|
+
attribute :type, :string, values: Enums::RESOLUTION_DATE_TYPE
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# The target resolution is an annex of the source resolution.
|
|
16
|
-
# }
|
|
17
|
-
|
|
18
|
-
# updates {
|
|
19
|
-
# This resolution updates the target resolution.
|
|
20
|
-
# }
|
|
21
|
-
|
|
22
|
-
# refines {
|
|
23
|
-
# This resolution refines the target resolution.
|
|
24
|
-
# }
|
|
25
|
-
|
|
26
|
-
# replaces/obsoletes {
|
|
27
|
-
# This resolution replaces/obsoletes the target resolution.
|
|
28
|
-
# }
|
|
29
|
-
|
|
30
|
-
# considers {
|
|
31
|
-
# This resolution is made in consideration of the target resolution.
|
|
32
|
-
# }
|
|
33
|
-
# }
|
|
11
|
+
key_value do
|
|
12
|
+
map "date", to: :date
|
|
13
|
+
map "type", to: :type
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edoxen
|
|
4
|
+
# Collection-level metadata: the title (string for default / single-language
|
|
5
|
+
# collections, or `title_localized[]` for multilingual), the meeting date,
|
|
6
|
+
# the source secretariat, per-language source PDFs, and the host venue.
|
|
7
|
+
class ResolutionMetadata < Lutaml::Model::Serializable
|
|
8
|
+
attribute :title, :string
|
|
9
|
+
attribute :title_localized, Localization, collection: true
|
|
10
|
+
attribute :date, :date
|
|
11
|
+
attribute :source, :string
|
|
12
|
+
attribute :source_urls, SourceUrl, collection: true
|
|
13
|
+
attribute :city, :string
|
|
14
|
+
attribute :country_code, :string
|
|
15
|
+
|
|
16
|
+
key_value do
|
|
17
|
+
map "title", to: :title
|
|
18
|
+
map "title_localized", to: :title_localized
|
|
19
|
+
map "date", to: :date
|
|
20
|
+
map "source", to: :source
|
|
21
|
+
map "source_urls", to: :source_urls
|
|
22
|
+
map "city", to: :city
|
|
23
|
+
map "country_code", to: :country_code
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edoxen
|
|
4
|
+
# Directed relation between two resolutions, identified by their
|
|
5
|
+
# StructuredIdentifier (prefix + number).
|
|
6
|
+
class ResolutionRelation < Lutaml::Model::Serializable
|
|
7
|
+
attribute :source, StructuredIdentifier
|
|
8
|
+
attribute :destination, StructuredIdentifier
|
|
9
|
+
attribute :type, :string, values: Enums::RESOLUTION_RELATION_TYPE
|
|
10
|
+
|
|
11
|
+
key_value do
|
|
12
|
+
map "source", to: :source
|
|
13
|
+
map "destination", to: :destination
|
|
14
|
+
map "type", to: :type
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "metadata"
|
|
5
|
+
require_relative "resolution"
|
|
6
|
+
|
|
7
|
+
module Edoxen
|
|
8
|
+
class ResolutionSet < Lutaml::Model::Serializable
|
|
9
|
+
attribute :metadata, Metadata
|
|
10
|
+
attribute :resolutions, Resolution, collection: true
|
|
11
|
+
|
|
12
|
+
key_value do
|
|
13
|
+
map "metadata", to: :metadata
|
|
14
|
+
map "resolutions", to: :resolutions
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|