edoxen 0.1.2 → 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/CLAUDE.md +220 -0
- data/README.adoc +153 -498
- data/lib/edoxen/_metadata.rb.deprecated +57 -0
- data/lib/edoxen/action.rb +5 -20
- data/lib/edoxen/approval.rb +6 -10
- data/lib/edoxen/cli.rb +70 -87
- data/lib/edoxen/consideration.rb +5 -13
- 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_identifier.rb +2 -6
- data/lib/edoxen/resolution.rb +19 -32
- data/lib/edoxen/resolution_collection.rb +15 -0
- data/lib/edoxen/resolution_date.rb +7 -8
- data/lib/edoxen/resolution_metadata.rb +26 -0
- data/lib/edoxen/resolution_relation.rb +5 -39
- data/lib/edoxen/schema_validator.rb +160 -248
- data/lib/edoxen/source_url.rb +18 -0
- data/lib/edoxen/structured_identifier.rb +17 -0
- data/lib/edoxen/url.rb +2 -3
- data/lib/edoxen/version.rb +1 -1
- data/lib/edoxen.rb +36 -14
- data/schema/edoxen.yaml +300 -339
- metadata +11 -3
- data/lib/edoxen/metadata.rb +0 -27
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "resolution_date"
|
|
5
|
+
require_relative "url"
|
|
6
|
+
require_relative "localization"
|
|
7
|
+
|
|
8
|
+
module Edoxen
|
|
9
|
+
# A per-language source-URL record. Carries the URL ref, its format
|
|
10
|
+
# (pdf, html, ...), and the language_code (ISO 639-3) for which the
|
|
11
|
+
# URL is the canonical source.
|
|
12
|
+
class SourceUrl < Lutaml::Model::Serializable
|
|
13
|
+
attribute :ref, :string
|
|
14
|
+
attribute :format, :string
|
|
15
|
+
attribute :language_code, :string
|
|
16
|
+
|
|
17
|
+
key_value do
|
|
18
|
+
map "ref", to: :ref
|
|
19
|
+
map "format", to: :format
|
|
20
|
+
map "language_code", to: :language_code
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Metadata < Lutaml::Model::Serializable
|
|
25
|
+
attribute :title, :string
|
|
26
|
+
attribute :identifier, :string
|
|
27
|
+
attribute :dates, ResolutionDate, collection: true
|
|
28
|
+
attribute :source, :string
|
|
29
|
+
attribute :venue, :string
|
|
30
|
+
attribute :chair, :string
|
|
31
|
+
attribute :urls, Url, collection: true
|
|
32
|
+
|
|
33
|
+
# OIML extensions — see TODO.complete/14 for the glossarist-style
|
|
34
|
+
# i18n model. `title_localized` carries the per-language title
|
|
35
|
+
# parallel to Resolution#localizations. `source_urls` carries the
|
|
36
|
+
# per-language PDF URLs. `city`/`country_code` carry the IATA /
|
|
37
|
+
# ISO 3166-1 alpha-2 codes for the host venue.
|
|
38
|
+
attribute :title_localized, Localization, collection: true
|
|
39
|
+
attribute :source_urls, SourceUrl, collection: true
|
|
40
|
+
attribute :city, :string
|
|
41
|
+
attribute :country_code, :string
|
|
42
|
+
|
|
43
|
+
key_value do
|
|
44
|
+
map "title", to: :title
|
|
45
|
+
map "identifier", to: :identifier
|
|
46
|
+
map "dates", to: :dates
|
|
47
|
+
map "source", to: :source
|
|
48
|
+
map "venue", to: :venue
|
|
49
|
+
map "chair", to: :chair
|
|
50
|
+
map "urls", to: :urls
|
|
51
|
+
map "title_localized", to: :title_localized
|
|
52
|
+
map "source_urls", to: :source_urls
|
|
53
|
+
map "city", to: :city
|
|
54
|
+
map "country_code", to: :country_code
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/edoxen/action.rb
CHANGED
|
@@ -1,32 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
require_relative "resolution_date"
|
|
5
|
-
|
|
6
3
|
module Edoxen
|
|
4
|
+
# Verb + one effective date + human-readable message. Used inside a
|
|
5
|
+
# Localization to express the multilingual part of an action.
|
|
7
6
|
class Action < Lutaml::Model::Serializable
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
appreciation approves asks assigns chairs communicating confirms consults considers
|
|
11
|
-
creates decides defines delegates delivering directs disbands drafting elects
|
|
12
|
-
empowers encourages endorses estabilishes establishes gathering identifies
|
|
13
|
-
instructs investigates notes notifies recognises nominates
|
|
14
|
-
recognizes recommends registers regrets request requests resolves restates reminds replaces
|
|
15
|
-
scopes secures sends supports thanks welcomes withdraws
|
|
16
|
-
].freeze
|
|
17
|
-
|
|
18
|
-
attribute :type, :string, values: ACTION_TYPE_ENUM
|
|
19
|
-
attribute :dates, ResolutionDate, collection: true
|
|
7
|
+
attribute :type, :string, values: Enums::ACTION_TYPE
|
|
8
|
+
attribute :date_effective, ResolutionDate
|
|
20
9
|
attribute :message, :string
|
|
21
|
-
attribute :subject, :string
|
|
22
|
-
attribute :degree, :string
|
|
23
10
|
|
|
24
11
|
key_value do
|
|
25
12
|
map "type", to: :type
|
|
13
|
+
map "date_effective", to: :date_effective
|
|
26
14
|
map "message", to: :message
|
|
27
|
-
map "subject", to: :subject
|
|
28
|
-
map "degree", to: :degree
|
|
29
|
-
map "dates", to: :dates
|
|
30
15
|
end
|
|
31
16
|
end
|
|
32
17
|
end
|
data/lib/edoxen/approval.rb
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
require_relative "resolution_date"
|
|
5
|
-
|
|
6
3
|
module Edoxen
|
|
4
|
+
# Approval record: type (affirmative / negative), degree (consensus level),
|
|
5
|
+
# date of the approval event, and a human-readable elaboration.
|
|
7
6
|
class Approval < Lutaml::Model::Serializable
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
attribute :type, :string, values: APPROVAL_TYPE_ENUM
|
|
12
|
-
attribute :degree, :string, values: APPROVAL_DEGREE_ENUM
|
|
13
|
-
attribute :dates, ResolutionDate, collection: true
|
|
7
|
+
attribute :type, :string, values: Enums::APPROVAL_TYPE
|
|
8
|
+
attribute :degree, :string, values: Enums::APPROVAL_DEGREE
|
|
9
|
+
attribute :date, ResolutionDate
|
|
14
10
|
attribute :message, :string
|
|
15
11
|
|
|
16
12
|
key_value do
|
|
17
13
|
map "type", to: :type
|
|
18
14
|
map "degree", to: :degree
|
|
19
|
-
map "
|
|
15
|
+
map "date", to: :date
|
|
20
16
|
map "message", to: :message
|
|
21
17
|
end
|
|
22
18
|
end
|
data/lib/edoxen/cli.rb
CHANGED
|
@@ -2,14 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
require "thor"
|
|
4
4
|
require "fileutils"
|
|
5
|
-
require_relative "schema_validator"
|
|
6
5
|
|
|
7
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.
|
|
8
17
|
class Cli < Thor
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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."
|
|
12
22
|
|
|
23
|
+
def validate(pattern)
|
|
24
|
+
files = expand_yaml_pattern(pattern)
|
|
13
25
|
if files.empty?
|
|
14
26
|
say "No files found matching pattern: #{pattern}", :red
|
|
15
27
|
exit 1
|
|
@@ -24,17 +36,8 @@ module Edoxen
|
|
|
24
36
|
files.each do |file|
|
|
25
37
|
print " #{File.basename(file)}... "
|
|
26
38
|
|
|
27
|
-
# Schema validation
|
|
28
39
|
schema_errors = validator.validate_file(file)
|
|
29
|
-
|
|
30
|
-
# Model parsing validation
|
|
31
|
-
model_errors = []
|
|
32
|
-
begin
|
|
33
|
-
content = File.read(file)
|
|
34
|
-
Edoxen::ResolutionSet.from_yaml(content)
|
|
35
|
-
rescue StandardError => e
|
|
36
|
-
model_errors << "Model parsing failed: #{e.message}"
|
|
37
|
-
end
|
|
40
|
+
model_errors = collect_model_errors(file)
|
|
38
41
|
|
|
39
42
|
if schema_errors.empty? && model_errors.empty?
|
|
40
43
|
say "✅ VALID", :green
|
|
@@ -42,36 +45,21 @@ module Edoxen
|
|
|
42
45
|
else
|
|
43
46
|
say "❌ INVALID", :red
|
|
44
47
|
invalid_count += 1
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
unless schema_errors.empty?
|
|
48
|
-
say " Schema Validation Errors:", :red
|
|
49
|
-
schema_errors.each do |error|
|
|
50
|
-
say " #{error.to_clickable_format}", :red
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Show model parsing errors
|
|
55
|
-
unless model_errors.empty?
|
|
56
|
-
say " Model Parsing Errors:", :red
|
|
57
|
-
model_errors.each do |error|
|
|
58
|
-
say " #{file}:1:1: #{error}", :red
|
|
59
|
-
end
|
|
60
|
-
end
|
|
48
|
+
schema_errors.each { |e| say " #{e.to_clickable_format}", :red }
|
|
49
|
+
model_errors.each { |m| say " #{file}:1:1: #{m}", :red }
|
|
61
50
|
end
|
|
62
51
|
end
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
say " Valid files: #{valid_count}", :green
|
|
66
|
-
say " Invalid files: #{invalid_count}", invalid_count.positive? ? :red : :green
|
|
67
|
-
say " Success rate: #{((valid_count.to_f / files.size) * 100).round(1)}%", :blue
|
|
68
|
-
|
|
53
|
+
print_summary(files.size, valid_count, invalid_count, validator_type: :binary)
|
|
69
54
|
exit(invalid_count.positive? ? 1 : 0)
|
|
70
55
|
end
|
|
71
56
|
|
|
72
|
-
desc "normalize YAML_FILE_PATTERN",
|
|
57
|
+
desc "normalize YAML_FILE_PATTERN",
|
|
58
|
+
"Round-trip YAML file(s) through the Edoxen model (--output DIR or --inplace)."
|
|
59
|
+
|
|
73
60
|
option :output, type: :string, desc: "Output directory for normalized files"
|
|
74
61
|
option :inplace, type: :boolean, desc: "Modify files in place (no backup)"
|
|
62
|
+
|
|
75
63
|
def normalize(pattern)
|
|
76
64
|
if options[:output] && options[:inplace]
|
|
77
65
|
say "Error: Cannot use both --output and --inplace options", :red
|
|
@@ -83,8 +71,7 @@ module Edoxen
|
|
|
83
71
|
exit 1
|
|
84
72
|
end
|
|
85
73
|
|
|
86
|
-
files =
|
|
87
|
-
|
|
74
|
+
files = expand_yaml_pattern(pattern)
|
|
88
75
|
if files.empty?
|
|
89
76
|
say "No files found matching pattern: #{pattern}", :red
|
|
90
77
|
exit 1
|
|
@@ -97,77 +84,73 @@ module Edoxen
|
|
|
97
84
|
|
|
98
85
|
files.each do |file|
|
|
99
86
|
print " #{File.basename(file)}... "
|
|
100
|
-
|
|
101
87
|
begin
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
# Extract yaml-language-server comment if present
|
|
106
|
-
yaml_language_server_comment = extract_yaml_language_server_comment(content)
|
|
107
|
-
|
|
108
|
-
resolution_set = Edoxen::ResolutionSet.from_yaml(content)
|
|
109
|
-
|
|
110
|
-
# Normalize by serializing back to YAML
|
|
111
|
-
normalized_yaml = resolution_set.to_yaml
|
|
112
|
-
|
|
113
|
-
# Prepend the yaml-language-server comment if it was present
|
|
114
|
-
normalized_yaml = "#{yaml_language_server_comment}\n#{normalized_yaml}" if yaml_language_server_comment
|
|
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
|
|
115
91
|
|
|
116
92
|
if options[:inplace]
|
|
117
|
-
|
|
118
|
-
File.write(file, normalized_yaml)
|
|
93
|
+
File.write(file, normalized)
|
|
119
94
|
say "✅ NORMALIZED", :green
|
|
120
95
|
else
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
say "✅ NORMALIZED → #{output_file}", :green
|
|
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
|
|
126
100
|
end
|
|
127
|
-
|
|
128
101
|
success_count += 1
|
|
129
102
|
rescue StandardError => e
|
|
130
|
-
say "❌ FAILED", :red
|
|
131
|
-
say " Error: #{e.message}", :red
|
|
103
|
+
say "❌ FAILED — #{e.message}", :red
|
|
132
104
|
error_count += 1
|
|
133
105
|
end
|
|
134
106
|
end
|
|
135
107
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if options[:output]
|
|
142
|
-
say " Output directory: #{options[:output]}", :blue
|
|
143
|
-
elsif options[:inplace]
|
|
144
|
-
say " Files modified in place", :yellow
|
|
145
|
-
end
|
|
146
|
-
|
|
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)
|
|
147
113
|
exit(error_count.positive? ? 1 : 0)
|
|
148
114
|
end
|
|
149
115
|
|
|
116
|
+
no_commands do
|
|
117
|
+
# Reserved for private Thor plumbing if we add it later.
|
|
118
|
+
end
|
|
119
|
+
|
|
150
120
|
private
|
|
151
121
|
|
|
152
|
-
def
|
|
153
|
-
|
|
154
|
-
|
|
122
|
+
def expand_yaml_pattern(pattern)
|
|
123
|
+
Dir.glob(pattern).select { |f| File.file?(f) && f.match?(/\.ya?ml\z/i) }.sort
|
|
124
|
+
end
|
|
155
125
|
|
|
156
|
-
|
|
157
|
-
|
|
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}"]
|
|
158
135
|
end
|
|
159
136
|
|
|
160
137
|
def extract_yaml_language_server_comment(content)
|
|
161
|
-
lines = content.split("\n")
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
lines.first(5).each do |line|
|
|
165
|
-
if line.strip.match?(/^#\s*yaml-language-server:\s*\$schema=/)
|
|
166
|
-
return line.rstrip # Only strip trailing whitespace, keep the #
|
|
167
|
-
end
|
|
168
|
-
end
|
|
138
|
+
lines = content.split("\n").first(5)
|
|
139
|
+
lines.find { |l| l.strip.match?(/\A#\s*yaml-language-server:\s*\$schema=/) }&.rstrip
|
|
140
|
+
end
|
|
169
141
|
|
|
170
|
-
|
|
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 }
|
|
171
154
|
end
|
|
172
155
|
end
|
|
173
156
|
end
|
data/lib/edoxen/consideration.rb
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
require_relative "resolution_date"
|
|
5
|
-
|
|
6
3
|
module Edoxen
|
|
4
|
+
# Basis for a resolution: a verb (having, noting, considering, ...) plus
|
|
5
|
+
# one effective date and the elaborated reasoning.
|
|
7
6
|
class Consideration < Lutaml::Model::Serializable
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
recognising recognizing
|
|
11
|
-
].freeze
|
|
12
|
-
|
|
13
|
-
attribute :type, :string, values: CONSIDERATION_TYPE_ENUM
|
|
14
|
-
attribute :dates, ResolutionDate, collection: true
|
|
7
|
+
attribute :type, :string, values: Enums::CONSIDERATION_TYPE
|
|
8
|
+
attribute :date_effective, ResolutionDate
|
|
15
9
|
attribute :message, :string
|
|
16
|
-
attribute :subject, :string
|
|
17
10
|
|
|
18
11
|
key_value do
|
|
19
12
|
map "type", to: :type
|
|
20
|
-
map "
|
|
13
|
+
map "date_effective", to: :date_effective
|
|
21
14
|
map "message", to: :message
|
|
22
|
-
map "subject", to: :subject
|
|
23
15
|
end
|
|
24
16
|
end
|
|
25
17
|
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,47 +1,34 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
require_relative "resolution_date"
|
|
5
|
-
require_relative "consideration"
|
|
6
|
-
require_relative "approval"
|
|
7
|
-
require_relative "action"
|
|
8
|
-
require_relative "meeting_identifier"
|
|
9
|
-
require_relative "resolution_relation"
|
|
10
|
-
|
|
11
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).
|
|
12
7
|
class Resolution < Lutaml::Model::Serializable
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
15
13
|
attribute :dates, ResolutionDate, collection: true
|
|
16
|
-
attribute :subject, :string
|
|
17
|
-
attribute :title, :string
|
|
18
|
-
attribute :type, :string, values: RESOLUTION_TYPE_ENUM
|
|
19
|
-
attribute :identifier, :string
|
|
20
|
-
attribute :message, :string
|
|
21
|
-
attribute :considering, :string
|
|
22
|
-
attribute :considerations, Consideration, collection: true
|
|
23
|
-
attribute :approvals, Approval, collection: true
|
|
24
|
-
attribute :actions, Action, collection: true
|
|
25
|
-
attribute :meeting_identifier, MeetingIdentifier
|
|
26
|
-
attribute :relations, ResolutionRelation, collection: true
|
|
27
14
|
attribute :categories, :string, collection: true
|
|
15
|
+
attribute :meeting, MeetingIdentifier
|
|
16
|
+
attribute :relations, ResolutionRelation, collection: true
|
|
28
17
|
attribute :urls, Url, collection: true
|
|
18
|
+
attribute :localizations, Localization, collection: true
|
|
29
19
|
|
|
30
20
|
key_value do
|
|
31
|
-
map "dates", to: :dates
|
|
32
|
-
map "subject", to: :subject
|
|
33
|
-
map "title", to: :title
|
|
34
|
-
map "type", to: :type
|
|
35
21
|
map "identifier", to: :identifier
|
|
36
|
-
map "
|
|
37
|
-
map "
|
|
38
|
-
map "
|
|
39
|
-
map "
|
|
40
|
-
map "
|
|
41
|
-
map "meeting_identifier", to: :meeting_identifier
|
|
42
|
-
map "relations", to: :relations
|
|
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
|
|
43
27
|
map "categories", to: :categories
|
|
28
|
+
map "meeting", to: :meeting
|
|
29
|
+
map "relations", to: :relations
|
|
44
30
|
map "urls", to: :urls
|
|
31
|
+
map "localizations", to: :localizations
|
|
45
32
|
end
|
|
46
33
|
end
|
|
47
34
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edoxen
|
|
4
|
+
# Top-level container for a published resolution collection: metadata
|
|
5
|
+
# plus the list of resolutions.
|
|
6
|
+
class ResolutionCollection < Lutaml::Model::Serializable
|
|
7
|
+
attribute :metadata, ResolutionMetadata
|
|
8
|
+
attribute :resolutions, Resolution, collection: true
|
|
9
|
+
|
|
10
|
+
key_value do
|
|
11
|
+
map "metadata", to: :metadata
|
|
12
|
+
map "resolutions", to: :resolutions
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "lutaml/model"
|
|
4
|
-
|
|
5
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.
|
|
6
7
|
class ResolutionDate < Lutaml::Model::Serializable
|
|
7
|
-
attribute :
|
|
8
|
-
attribute :
|
|
9
|
-
attribute :kind, :string, values: %w[ballot enactment effective decision meeting]
|
|
8
|
+
attribute :date, :date
|
|
9
|
+
attribute :type, :string, values: Enums::RESOLUTION_DATE_TYPE
|
|
10
10
|
|
|
11
11
|
key_value do
|
|
12
|
-
map "
|
|
13
|
-
map "
|
|
14
|
-
map "kind", to: :kind
|
|
12
|
+
map "date", to: :date
|
|
13
|
+
map "type", to: :type
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
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
|
|
@@ -1,46 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# class ResolutionRelation {
|
|
4
|
-
# source: StructuredIdentifier (Resolution)
|
|
5
|
-
# destination: StructuredIdentifier (Resolution)
|
|
6
|
-
# type: ResolutionRelationType
|
|
7
|
-
# }
|
|
8
|
-
|
|
9
|
-
# enum ResolutionRelationType {
|
|
10
|
-
# annexOf {
|
|
11
|
-
# This resolution is an annex to the target resolution.
|
|
12
|
-
# }
|
|
13
|
-
|
|
14
|
-
# hasAnnex {
|
|
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
|
-
# }
|
|
34
|
-
|
|
35
|
-
require "lutaml/model"
|
|
36
|
-
|
|
37
3
|
module Edoxen
|
|
4
|
+
# Directed relation between two resolutions, identified by their
|
|
5
|
+
# StructuredIdentifier (prefix + number).
|
|
38
6
|
class ResolutionRelation < Lutaml::Model::Serializable
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
attribute :
|
|
42
|
-
attribute :destination, :string
|
|
43
|
-
attribute :type, :string, values: RESOLUTION_RELATIONSHIP_ENUM
|
|
7
|
+
attribute :source, StructuredIdentifier
|
|
8
|
+
attribute :destination, StructuredIdentifier
|
|
9
|
+
attribute :type, :string, values: Enums::RESOLUTION_RELATION_TYPE
|
|
44
10
|
|
|
45
11
|
key_value do
|
|
46
12
|
map "source", to: :source
|