genericode 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +27 -1
- data/.rubocop_todo.yml +51 -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 +70 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a658f75042c1064fc1032f885e266baeb816d38fd1f48324bdc791739abbd71e
|
4
|
+
data.tar.gz: 7ebc14d95ed7538b3c3991baba75b78bd0661102e00e85625a7ef17f6d47ed1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 304c01513d153bb25eed9cfc146a1502e2212404aa138574ded480e503142a1f2b11891e1ebddd08373780fef19d95133a2b97f969ef2501bb6bdb15b7aba3f8
|
7
|
+
data.tar.gz: 5f801ef2ea74a25c30c1a189c9cf5d55d768f45cac0d223436d3e6bb0d2e26610f7c7c4efaf09ca604396e61c7192135532f75bfa2e6997b7fac321015163e0d
|
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,51 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2024-08-27 09:46:41 UTC using RuboCop version 1.65.1.
|
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: 1
|
10
|
+
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches.
|
11
|
+
Lint/DuplicateBranch:
|
12
|
+
Exclude:
|
13
|
+
- 'lib/genericode/code_list.rb'
|
14
|
+
|
15
|
+
# Offense count: 8
|
16
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
17
|
+
Metrics/AbcSize:
|
18
|
+
Max: 182
|
19
|
+
|
20
|
+
# Offense count: 2
|
21
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
22
|
+
# AllowedMethods: refine
|
23
|
+
Metrics/BlockLength:
|
24
|
+
Max: 34
|
25
|
+
|
26
|
+
# Offense count: 1
|
27
|
+
# Configuration parameters: CountComments, CountAsOne.
|
28
|
+
Metrics/ClassLength:
|
29
|
+
Max: 220
|
30
|
+
|
31
|
+
# Offense count: 5
|
32
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
33
|
+
Metrics/CyclomaticComplexity:
|
34
|
+
Max: 92
|
35
|
+
|
36
|
+
# Offense count: 10
|
37
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
38
|
+
Metrics/MethodLength:
|
39
|
+
Max: 86
|
40
|
+
|
41
|
+
# Offense count: 3
|
42
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
43
|
+
Metrics/PerceivedComplexity:
|
44
|
+
Max: 92
|
45
|
+
|
46
|
+
# Offense count: 2
|
47
|
+
# This cop supports safe autocorrection (--autocorrect).
|
48
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
49
|
+
# URISchemes: http, https
|
50
|
+
Layout/LineLength:
|
51
|
+
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
|