genericode 0.1.0 → 0.1.2
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.yml +27 -1
- data/.rubocop_todo.yml +66 -0
- data/README.adoc +282 -0
- data/exe/genericode +7 -0
- data/lib/genericode/agency.rb +25 -5
- data/lib/genericode/annotation.rb +10 -4
- data/lib/genericode/any_other_content.rb +2 -2
- data/lib/genericode/any_other_language_content.rb +3 -3
- data/lib/genericode/canonical_uri.rb +32 -0
- data/lib/genericode/cli/code_lister.rb +67 -0
- data/lib/genericode/cli/code_lookup.rb +22 -0
- data/lib/genericode/cli/commands.rb +76 -0
- data/lib/genericode/cli/converter.rb +35 -0
- data/lib/genericode/cli/validator.rb +21 -0
- data/lib/genericode/cli.rb +8 -0
- data/lib/genericode/code_list.rb +257 -9
- data/lib/genericode/code_list_ref.rb +9 -6
- data/lib/genericode/code_list_set.rb +39 -2
- data/lib/genericode/code_list_set_ref.rb +9 -6
- data/lib/genericode/column.rb +37 -11
- data/lib/genericode/column_ref.rb +7 -7
- data/lib/genericode/column_set.rb +3 -3
- data/lib/genericode/column_set_ref.rb +4 -4
- data/lib/genericode/data.rb +5 -5
- data/lib/genericode/data_restrictions.rb +3 -3
- data/lib/genericode/datatype_facet.rb +10 -7
- data/lib/genericode/general_identifier.rb +6 -6
- data/lib/genericode/identification.rb +53 -11
- data/lib/genericode/json/canonical_uri_mixin.rb +17 -0
- data/lib/genericode/json/short_name_mixin.rb +17 -0
- data/lib/genericode/key.rb +34 -9
- data/lib/genericode/key_column_ref.rb +3 -3
- data/lib/genericode/key_ref.rb +6 -6
- data/lib/genericode/long_name.rb +17 -7
- data/lib/genericode/mime_typed_uri.rb +5 -5
- data/lib/genericode/row.rb +2 -2
- data/lib/genericode/short_name.rb +10 -5
- data/lib/genericode/simple_code_list.rb +2 -2
- data/lib/genericode/simple_value.rb +3 -3
- data/lib/genericode/utils.rb +50 -0
- data/lib/genericode/value.rb +5 -4
- data/lib/genericode/version.rb +1 -1
- data/lib/genericode.rb +12 -0
- data/oasis-reqs-implemented.md +31 -0
- data/oasis-requirements-1.0.md +56 -0
- metadata +28 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45525e09245553fcda6cb3606ec8f7b17c0fde0daf6507c41e47008d5e8dce43
|
4
|
+
data.tar.gz: 66c0b7b056d47c096d736176d9c575df8fba8c830f539d14e076b43a6f07cda8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6dd2ebe439fde9ab7584ef67e149b3d79b026ae980b8beec200c5fd99a45e95c35b70663bfd8d27566095778394ce6a65ad2f4e7ff72b4706b7028c94ba55a5
|
7
|
+
data.tar.gz: 59951937dd0cd26496fe64e13f9ba70c12ed7d2757609ebfa10633e4d21a233fae230fc234b7da559f4bc12e1c121b029bec786af445f74d6fd5a703dcff83b0
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,34 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
1
3
|
AllCops:
|
2
|
-
|
4
|
+
NewCops: enable
|
5
|
+
SuggestExtensions: false
|
6
|
+
TargetRubyVersion: 2.7
|
7
|
+
|
8
|
+
Gemspec/DevelopmentDependencies:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Gemspec/RequireMFA:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Metrics/BlockLength:
|
15
|
+
AllowedMethods:
|
16
|
+
- describe
|
17
|
+
|
18
|
+
Style/Documentation:
|
19
|
+
Enabled: false
|
3
20
|
|
4
21
|
Style/StringLiterals:
|
5
22
|
EnforcedStyle: double_quotes
|
6
23
|
|
7
24
|
Style/StringLiteralsInInterpolation:
|
8
25
|
EnforcedStyle: double_quotes
|
26
|
+
|
27
|
+
Style/TrailingCommaInArguments:
|
28
|
+
EnforcedStyleForMultiline: consistent_comma
|
29
|
+
|
30
|
+
Style/TrailingCommaInArrayLiteral:
|
31
|
+
EnforcedStyleForMultiline: consistent_comma
|
32
|
+
|
33
|
+
Style/TrailingCommaInHashLiteral:
|
34
|
+
EnforcedStyleForMultiline: consistent_comma
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2025-01-11 09:46:54 UTC using RuboCop version 1.70.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 4
|
10
|
+
# This cop supports safe autocorrection (--autocorrect).
|
11
|
+
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
|
12
|
+
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
13
|
+
Bundler/OrderedGems:
|
14
|
+
Exclude:
|
15
|
+
- 'Gemfile'
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
19
|
+
Lint/DuplicateBranch:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/genericode/code_list.rb'
|
22
|
+
|
23
|
+
# Offense count: 1
|
24
|
+
# This cop supports safe autocorrection (--autocorrect).
|
25
|
+
# Configuration parameters: AutoCorrect, CheckForMethodsWithNoSideEffects.
|
26
|
+
Lint/Void:
|
27
|
+
Exclude:
|
28
|
+
- 'lib/genericode/code_list.rb'
|
29
|
+
|
30
|
+
# Offense count: 8
|
31
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
32
|
+
Metrics/AbcSize:
|
33
|
+
Max: 182
|
34
|
+
|
35
|
+
# Offense count: 2
|
36
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
37
|
+
# AllowedMethods: refine
|
38
|
+
Metrics/BlockLength:
|
39
|
+
Max: 34
|
40
|
+
|
41
|
+
# Offense count: 1
|
42
|
+
# Configuration parameters: CountComments, CountAsOne.
|
43
|
+
Metrics/ClassLength:
|
44
|
+
Max: 216
|
45
|
+
|
46
|
+
# Offense count: 5
|
47
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
48
|
+
Metrics/CyclomaticComplexity:
|
49
|
+
Max: 92
|
50
|
+
|
51
|
+
# Offense count: 10
|
52
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
53
|
+
Metrics/MethodLength:
|
54
|
+
Max: 86
|
55
|
+
|
56
|
+
# Offense count: 3
|
57
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
58
|
+
Metrics/PerceivedComplexity:
|
59
|
+
Max: 92
|
60
|
+
|
61
|
+
# Offense count: 2
|
62
|
+
# This cop supports safe autocorrection (--autocorrect).
|
63
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
64
|
+
# URISchemes: http, https
|
65
|
+
Layout/LineLength:
|
66
|
+
Max: 121
|
data/README.adoc
ADDED
@@ -0,0 +1,282 @@
|
|
1
|
+
= Genericode
|
2
|
+
|
3
|
+
image:https://img.shields.io/gem/v/genericode.svg["Gem Version", link="https://rubygems.org/gems/genericode"]
|
4
|
+
image:https://github.com/lutaml/genericode/workflows/rake/badge.svg["Build Status", link="https://github.com/lutaml/genericode/actions?workflow=rake"]
|
5
|
+
image:https://codeclimate.com/github/lutaml/genericode/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/lutaml/genericode"]
|
6
|
+
|
7
|
+
== Purpose
|
8
|
+
|
9
|
+
This Ruby gem implements the
|
10
|
+
http://docs.oasis-open.org/codelist/genericode/doc/oasis-code-list-representation-genericode.html[OASIS Genericode 1.0 standard].
|
11
|
+
|
12
|
+
It can be used to parse and generate code lists in the Genericode format,
|
13
|
+
including:
|
14
|
+
|
15
|
+
* Genericode XML: `*.gc`
|
16
|
+
* Genericode JSON: `*.gcj`
|
17
|
+
|
18
|
+
|
19
|
+
== Installation
|
20
|
+
|
21
|
+
To install the genericode gem, use one of the following methods.
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
[source,ruby]
|
26
|
+
----
|
27
|
+
gem 'genericode'
|
28
|
+
----
|
29
|
+
|
30
|
+
Then execute:
|
31
|
+
|
32
|
+
[source,sh]
|
33
|
+
----
|
34
|
+
$ bundle install
|
35
|
+
----
|
36
|
+
|
37
|
+
Or install it directly using:
|
38
|
+
|
39
|
+
[source,sh]
|
40
|
+
----
|
41
|
+
$ gem install genericode
|
42
|
+
----
|
43
|
+
|
44
|
+
After installation, you can start using the genericode gem in your Ruby projects
|
45
|
+
or via the command-line interface.
|
46
|
+
|
47
|
+
|
48
|
+
== Genericode path syntax
|
49
|
+
|
50
|
+
The "Genericode path" is a simplified syntax used to navigate through and
|
51
|
+
extract data from Genericode structures. It's designed to be intuitive and
|
52
|
+
flexible.
|
53
|
+
|
54
|
+
=== Basic syntax
|
55
|
+
|
56
|
+
The basic syntax uses a combination of column names and values to uniquely
|
57
|
+
identify a row and retrieve associated data:
|
58
|
+
|
59
|
+
----
|
60
|
+
column_name:value
|
61
|
+
----
|
62
|
+
|
63
|
+
This will return all data associated with the row where `column_name` has the
|
64
|
+
specified `value`.
|
65
|
+
|
66
|
+
=== Multiple column lookup
|
67
|
+
|
68
|
+
To narrow down the search using multiple columns:
|
69
|
+
|
70
|
+
----
|
71
|
+
column1:value1,column2:value2
|
72
|
+
----
|
73
|
+
|
74
|
+
This will return data for the row where `column1` has `value1` AND `column2` has
|
75
|
+
`value2`.
|
76
|
+
|
77
|
+
=== Specific column retrieval
|
78
|
+
|
79
|
+
To retrieve the value of a specific column for a given row:
|
80
|
+
|
81
|
+
----
|
82
|
+
column1:value1>target_column
|
83
|
+
----
|
84
|
+
|
85
|
+
This will return the value of `target_column` for the row where `column1` has
|
86
|
+
`value1`.
|
87
|
+
|
88
|
+
|
89
|
+
== CLI commands
|
90
|
+
|
91
|
+
The Genericode gem provides a command-line interface (CLI) with the following
|
92
|
+
commands:
|
93
|
+
|
94
|
+
=== Convert
|
95
|
+
|
96
|
+
Converts between Genericode XML and JSON formats.
|
97
|
+
|
98
|
+
Usage:
|
99
|
+
[source,sh]
|
100
|
+
----
|
101
|
+
$ genericode convert INPUT_FILE OUTPUT_FILE
|
102
|
+
----
|
103
|
+
|
104
|
+
Example:
|
105
|
+
[source,sh]
|
106
|
+
----
|
107
|
+
$ genericode convert input.gc output.gcj
|
108
|
+
----
|
109
|
+
|
110
|
+
This command is useful when you need to convert between XML and JSON
|
111
|
+
representations of your code lists.
|
112
|
+
|
113
|
+
=== Validate
|
114
|
+
|
115
|
+
Validates a Genericode file.
|
116
|
+
|
117
|
+
Usage:
|
118
|
+
[source,sh]
|
119
|
+
----
|
120
|
+
$ genericode validate FILE
|
121
|
+
----
|
122
|
+
|
123
|
+
Example:
|
124
|
+
[source,sh]
|
125
|
+
----
|
126
|
+
$ genericode validate codelist.gc
|
127
|
+
----
|
128
|
+
|
129
|
+
Use this command to check if your Genericode file is valid according to the
|
130
|
+
specification.
|
131
|
+
|
132
|
+
=== List codes
|
133
|
+
|
134
|
+
Lists all codes and their associated data in a Genericode file.
|
135
|
+
|
136
|
+
Usage:
|
137
|
+
[source,sh]
|
138
|
+
----
|
139
|
+
$ genericode list_codes FILE [--format=FORMAT] [--output=FILE]
|
140
|
+
----
|
141
|
+
|
142
|
+
Example:
|
143
|
+
[source,sh]
|
144
|
+
----
|
145
|
+
$ genericode list_codes country_codes.gc
|
146
|
+
$ genericode list_codes country_codes.gc --format=table
|
147
|
+
$ genericode list_codes country_codes.gc --format=tsv --output=codes.tsv
|
148
|
+
----
|
149
|
+
|
150
|
+
This command displays all the data in the Genericode file. By default, it
|
151
|
+
outputs in TSV (Tab-Separated Values) format. You can specify the `--format`
|
152
|
+
option to choose between `tsv` (default) and `table` formats. Use the `--output`
|
153
|
+
option to save the result to a file.
|
154
|
+
|
155
|
+
=== Lookup
|
156
|
+
|
157
|
+
Looks up specific data in a Genericode file using the simplified Genericode path
|
158
|
+
syntax.
|
159
|
+
|
160
|
+
Usage:
|
161
|
+
[source,sh]
|
162
|
+
----
|
163
|
+
$ genericode lookup FILE PATH
|
164
|
+
----
|
165
|
+
|
166
|
+
Examples:
|
167
|
+
[source,sh]
|
168
|
+
----
|
169
|
+
$ genericode lookup country_codes.gc "code:US"
|
170
|
+
$ genericode lookup country_codes.gc "code:FR>name"
|
171
|
+
$ genericode lookup currency_codes.gc "alpha_code:USD,numeric_code:840>name"
|
172
|
+
----
|
173
|
+
|
174
|
+
Use this command to extract specific information from a Genericode file using
|
175
|
+
the simplified path syntax. The syntax allows you to:
|
176
|
+
|
177
|
+
* Retrieve all data for a specific code: `column:value`
|
178
|
+
* Get a specific column value for a given code: `column:value>target_column`
|
179
|
+
* Use multiple columns to narrow down the search: `column1:value1,column2:value2`
|
180
|
+
|
181
|
+
To use these CLI commands, ensure that the Genericode gem is installed and
|
182
|
+
available in your system's PATH.
|
183
|
+
|
184
|
+
== Ruby API
|
185
|
+
|
186
|
+
[source,ruby]
|
187
|
+
----
|
188
|
+
require 'genericode'
|
189
|
+
|
190
|
+
# Load a Genericode file
|
191
|
+
gc = Genericode::CodeList.from_file("country_codes.gc")
|
192
|
+
|
193
|
+
# Lookup examples
|
194
|
+
gc.lookup("code:US")
|
195
|
+
# => {"code"=>"US", "name"=>"United States", ...}
|
196
|
+
|
197
|
+
gc.lookup("code:FR>name")
|
198
|
+
# => "France"
|
199
|
+
|
200
|
+
gc.lookup("alpha_code:USD,numeric_code:840>name")
|
201
|
+
# => "US Dollar"
|
202
|
+
|
203
|
+
# Other API usage remains the same
|
204
|
+
gc.identification.short_name.content
|
205
|
+
# => "CountryCodes"
|
206
|
+
|
207
|
+
gc.simple_code_list.row.map(&:value).flatten.map(&:simple_value).map(&:content)
|
208
|
+
# => ["US", "United States", "FR", "France", ...]
|
209
|
+
----
|
210
|
+
|
211
|
+
[source,ruby]
|
212
|
+
----
|
213
|
+
require 'genericode'
|
214
|
+
|
215
|
+
# XML element root of `<<gc:CodeList>`
|
216
|
+
gc = Genericode::CodeList.from_xml(File.read("spec/fixtures/xml/CaseTypeCode.gc"))
|
217
|
+
# Or:
|
218
|
+
# JSON element root of `<<gc:CodeList>`
|
219
|
+
# gc = Genericode.from_json(File.read("spec/fixtures/json/CaseTypeCode.gcj"))
|
220
|
+
|
221
|
+
gc.identification.short_name.content
|
222
|
+
# => "CaseTypeCode"
|
223
|
+
gc.identification.short_name.version
|
224
|
+
# => "5.0"
|
225
|
+
|
226
|
+
gc.simple_code_list.row.map(&:value).flatten.map(&:simple_value).map(&:content)
|
227
|
+
# => ["appellate", "bankruptcy", "citation", "civil", "criminal", "domestic", "juvenile"]
|
228
|
+
----
|
229
|
+
|
230
|
+
[source,ruby]
|
231
|
+
----
|
232
|
+
require 'genericode'
|
233
|
+
|
234
|
+
# XML element root of `<<gc:CodeList>`
|
235
|
+
gc = Genericode::CodeList.from_json(File.read("spec/fixtures/xml/CaseTypeCode.gcj"))
|
236
|
+
|
237
|
+
gc.identification.short_name.content
|
238
|
+
# => "CaseTypeCode"
|
239
|
+
gc.identification.short_name.version
|
240
|
+
# => "5.0"
|
241
|
+
|
242
|
+
gc.simple_code_list.row.map(&:value).flatten.map(&:simple_value).map(&:content)
|
243
|
+
# => ["appellate", "bankruptcy", "citation", "civil", "criminal", "domestic", "juvenile"]
|
244
|
+
----
|
245
|
+
|
246
|
+
== Tests
|
247
|
+
|
248
|
+
The `spec/fixtures` folder tests the library against known examples of Genericode.
|
249
|
+
|
250
|
+
Including:
|
251
|
+
|
252
|
+
`spec/fixtures/json`:: JSON examples.
|
253
|
+
|
254
|
+
`spec/fixtures/json/standard/*.gcj`:: Genericode JSON examples from the OASIS
|
255
|
+
genericode standard 1.0
|
256
|
+
https://github.com/oasis-tcs/codelist-genericode/tree/genericode-v1.0-os/json-example[(GitHub)].
|
257
|
+
|
258
|
+
`spec/fixtures/xml`:: XML examples.
|
259
|
+
|
260
|
+
`spec/fixtures/xml/standard/*.gc`:: Genericode XML examples from the OASIS
|
261
|
+
genericode standard 1.0
|
262
|
+
https://github.com/oasis-tcs/codelist-genericode/tree/genericode-v1.0-os/xml[(GitHub)].
|
263
|
+
|
264
|
+
`spec/fixtures/xml/niem/*.gc`:: Genericode XML examples from the
|
265
|
+
https://reference.niem.gov/niem/specification/code-lists/1.0beta1/niem-code-lists-1.0beta1-2016-03-15.html[NIEM Code Lists Specification, Version 1.0beta1].
|
266
|
+
https://github.com/NIEM/NIEM-Code-Lists-Spec/blob/master/example/make-model/make-model.gc[(GitHub)]
|
267
|
+
+
|
268
|
+
NOTE: A modification was made to remove unrelated namespaces to allow tests to
|
269
|
+
pass.
|
270
|
+
|
271
|
+
`spec/fixtures/xml/ubl/*.gc`:: Genericode XML examples from the
|
272
|
+
https://github.com/oasis-tcs/ubl[OASIS UBL 2.3 repository] (branch `ubl-2.5-csd01`),
|
273
|
+
https://github.com/oasis-tcs/ubl/tree/ubl-2.5-csd01/os-UBL-2.3/cl/gc/default[`os-UBL-2.3/cl/gc/default`].
|
274
|
+
|
275
|
+
NOTE: The "OASIS genericode standard 1.0" refers to the
|
276
|
+
https://docs.oasis-open.org/codelist/genericode/v1.0/os/genericode-v1.0-os.html#S-LONGNAME-COMPLEX-TYPE["OASIS Code List Representation (genericode) Version 1.0"]
|
277
|
+
|
278
|
+
== License
|
279
|
+
|
280
|
+
Copyright Ribose.
|
281
|
+
|
282
|
+
BSD-3 license.
|
data/exe/genericode
ADDED
data/lib/genericode/agency.rb
CHANGED
@@ -1,21 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "lutaml/model"
|
4
4
|
|
5
5
|
require_relative "general_identifier"
|
6
6
|
require_relative "long_name"
|
7
7
|
require_relative "short_name"
|
8
|
+
require_relative "json/short_name_mixin"
|
9
|
+
require_relative "utils"
|
8
10
|
|
9
11
|
module Genericode
|
10
|
-
class Agency <
|
12
|
+
class Agency < Lutaml::Model::Serializable
|
13
|
+
include Json::ShortNameMixin
|
14
|
+
|
11
15
|
attribute :short_name, ShortName
|
12
16
|
attribute :long_name, LongName, collection: true
|
13
17
|
attribute :identifier, GeneralIdentifier, collection: true
|
14
18
|
|
15
19
|
json do
|
16
|
-
map "ShortName", to: :short_name
|
17
|
-
map "LongName", to: :long_name
|
18
|
-
map "Identifier", to: :identifier
|
20
|
+
map "ShortName", to: :short_name, with: { from: :short_name_from_json, to: :short_name_to_json }
|
21
|
+
map "LongName", to: :long_name, with: { from: :long_name_from_json, to: :long_name_to_json }
|
22
|
+
map "Identifier", to: :identifier, with: { from: :identifier_from_json, to: :identifier_to_json }
|
23
|
+
end
|
24
|
+
|
25
|
+
def long_name_from_json(model, value)
|
26
|
+
model.long_name = LongName.of_json(Utils.array_wrap(value))
|
27
|
+
end
|
28
|
+
|
29
|
+
def long_name_to_json(model, doc)
|
30
|
+
doc["LongName"] = LongName.as_json(Utils.one_or_all(model.long_name))
|
31
|
+
end
|
32
|
+
|
33
|
+
def identifier_from_json(model, value)
|
34
|
+
model.identifier = GeneralIdentifier.of_json(Utils.array_wrap(value))
|
35
|
+
end
|
36
|
+
|
37
|
+
def identifier_to_json(model, doc)
|
38
|
+
doc["Identifier"] = GeneralIdentifier.as_json(Utils.one_or_all(model.identifier))
|
19
39
|
end
|
20
40
|
|
21
41
|
xml do
|
@@ -1,18 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "lutaml/model"
|
4
4
|
|
5
5
|
require_relative "any_other_content"
|
6
6
|
require_relative "any_other_language_content"
|
7
7
|
|
8
8
|
module Genericode
|
9
|
-
class Annotation <
|
9
|
+
class Annotation < Lutaml::Model::Serializable
|
10
10
|
attribute :description, AnyOtherLanguageContent, collection: true
|
11
11
|
attribute :app_info, AnyOtherContent
|
12
12
|
|
13
13
|
json do
|
14
14
|
map "Description", to: :description
|
15
|
-
map "AppInfo", to: :app_info
|
15
|
+
map "AppInfo", to: :app_info, render_nil: true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.of_json(hash, **)
|
19
|
+
hash = { "AppInfo" => hash } if hash.any?
|
20
|
+
|
21
|
+
super
|
16
22
|
end
|
17
23
|
|
18
24
|
xml do
|
@@ -20,7 +26,7 @@ module Genericode
|
|
20
26
|
namespace "http://docs.oasis-open.org/codelist/ns/genericode/1.0/", "gc"
|
21
27
|
|
22
28
|
map_element "Description", to: :description, prefix: nil, namespace: nil
|
23
|
-
map_element "AppInfo", to: :app_info, prefix: nil, namespace: nil
|
29
|
+
map_element "AppInfo", to: :app_info, prefix: nil, namespace: nil, render_nil: true
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "lutaml/model"
|
4
4
|
|
5
5
|
module Genericode
|
6
|
-
class AnyOtherContent <
|
6
|
+
class AnyOtherContent < Lutaml::Model::Serializable
|
7
7
|
xml do
|
8
8
|
root "AnyOtherContent"
|
9
9
|
namespace "http://docs.oasis-open.org/codelist/ns/genericode/1.0/", "gc"
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "lutaml/model"
|
4
4
|
|
5
5
|
module Genericode
|
6
|
-
class AnyOtherLanguageContent <
|
7
|
-
attribute :lang,
|
6
|
+
class AnyOtherLanguageContent < Lutaml::Model::Serializable
|
7
|
+
attribute :lang, :string
|
8
8
|
|
9
9
|
json do
|
10
10
|
map "lang", to: :lang
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lutaml/model"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module Genericode
|
7
|
+
# Rule 4: Must be an absolute URI, must not be relative
|
8
|
+
class CanonicalUri < Lutaml::Model::Serializable
|
9
|
+
attribute :content, :string
|
10
|
+
|
11
|
+
xml do
|
12
|
+
root "CanonicalUri"
|
13
|
+
map_content to: :content
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
valid_uri?(content) && absolute_uri?(content)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def valid_uri?(uri)
|
23
|
+
uri =~ URI::DEFAULT_PARSER.make_regexp
|
24
|
+
end
|
25
|
+
|
26
|
+
def absolute_uri?(uri)
|
27
|
+
URI.parse(uri).absolute?
|
28
|
+
rescue URI::InvalidURIError
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../code_list"
|
4
|
+
require "tabulo"
|
5
|
+
require "csv"
|
6
|
+
|
7
|
+
module Genericode
|
8
|
+
module Cli
|
9
|
+
class CodeLister
|
10
|
+
class << self
|
11
|
+
def list_codes(file_path, format: :tsv)
|
12
|
+
code_list = CodeList.from_file(file_path)
|
13
|
+
|
14
|
+
# Validate data types
|
15
|
+
code_list.validate_verbose.each do |error|
|
16
|
+
raise Error, "#{error[:code]}: #{error[:message]}" if error[:code] == "INVALID_DATA_TYPE"
|
17
|
+
|
18
|
+
# Ensure valid ColumnRefs
|
19
|
+
raise Error, "#{error[:code]}: #{error[:message]}" if error[:code] == "INVALID_COLUMN_REF"
|
20
|
+
end
|
21
|
+
|
22
|
+
case format
|
23
|
+
when :tsv
|
24
|
+
list_tsv(code_list)
|
25
|
+
when :table
|
26
|
+
list_table(code_list)
|
27
|
+
else
|
28
|
+
raise Error, "Unknown format: #{format}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def list_tsv(code_list)
|
35
|
+
columns = code_list.column_set.column
|
36
|
+
rows = code_list.simple_code_list.row
|
37
|
+
|
38
|
+
CSV.generate(col_sep: "\t") do |csv|
|
39
|
+
csv << columns.map { |col| col.short_name.content }
|
40
|
+
rows.each do |row|
|
41
|
+
csv << columns.map do |col|
|
42
|
+
value = row.value.find { |v| v.column_ref == col.id }
|
43
|
+
value&.simple_value&.content || ""
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end.strip.encode("UTF-8")
|
47
|
+
end
|
48
|
+
|
49
|
+
def list_table(code_list)
|
50
|
+
columns = code_list.column_set.column
|
51
|
+
rows = code_list.simple_code_list.row
|
52
|
+
|
53
|
+
table = Tabulo::Table.new(rows) do |t|
|
54
|
+
columns.each do |column|
|
55
|
+
t.add_column(column.short_name.content) do |row|
|
56
|
+
value = row.value.find { |v| v.column_ref == column.id }
|
57
|
+
value&.simple_value&.content || ""
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
table.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../code_list"
|
4
|
+
|
5
|
+
module Genericode
|
6
|
+
module Cli
|
7
|
+
class CodeLookup
|
8
|
+
def self.lookup(file_path, path)
|
9
|
+
code_list = CodeList.from_file(file_path)
|
10
|
+
result = code_list.lookup(path)
|
11
|
+
|
12
|
+
if result.is_a?(Hash)
|
13
|
+
result.map { |k, v| "#{k}: #{v}" }.join("\n")
|
14
|
+
else
|
15
|
+
result.to_s
|
16
|
+
end
|
17
|
+
rescue Error => e
|
18
|
+
raise Error, e.message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|