relaton-iho 2.0.0.pre.alpha.3 → 2.0.3
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 +4 -0
- data/README.adoc +2 -0
- data/Rakefile +24 -0
- data/lib/relaton/iho/bibliography.rb +75 -7
- data/lib/relaton/iho/docidentifier.rb +35 -0
- data/lib/relaton/iho/ext.rb +3 -0
- data/lib/relaton/iho/hash_parser_v1.rb +15 -0
- data/lib/relaton/iho/item.rb +3 -0
- data/lib/relaton/iho/structured_identifier.rb +20 -0
- data/lib/relaton/iho/version.rb +1 -1
- data/lib/relaton/iho.rb +3 -1
- data/relaton_iho.gemspec +2 -1
- metadata +19 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 925a166a381b8adb5378310ef223267789270224fe165464a13f925077509b4d
|
|
4
|
+
data.tar.gz: 370e60d822569a76887517f7a78406573974ba1696cc6b789960c34108e2b61a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17f0a775934419440d44bb7eebfa9dea5e9057c0d642ddd508756a5f03b6e5c19ba8afbc84d295455d93b75d667f5abb7429d6bf3e43c8f1364b78020e2077e2
|
|
7
|
+
data.tar.gz: 67634f4b8e47c58e46e03ab5c6a27856c8cfa4ea0b9187ae93e957ff3612578c119dc586740eea0fd23140fa2ab333d62ec4794c1c11c6ce6357710a197a175e
|
data/CLAUDE.md
CHANGED
|
@@ -64,3 +64,7 @@ In `item.rb`, `require_relative "relation"` is placed **after** the `Item` class
|
|
|
64
64
|
### IHO-Specific Document Types
|
|
65
65
|
|
|
66
66
|
policy-and-procedures, best-practices, supporting-document, report, legal, directives, proposal, standard
|
|
67
|
+
|
|
68
|
+
## Testing
|
|
69
|
+
|
|
70
|
+
- **Index fixture:** `spec/fixtures/index-v1.zip` is pre-loaded into `Relaton::Index` pool in `before(:suite)` (configured in `spec/support/webmock.rb`). Run `rake spec:update_index` to refresh from relaton-data-iho.
|
data/README.adoc
CHANGED
|
@@ -137,6 +137,8 @@ RelatonIho uses the relaton-logger gem for logging. By default, it logs to STDOU
|
|
|
137
137
|
|
|
138
138
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
139
139
|
|
|
140
|
+
To update the index test fixture (used by tests), run `rake spec:update_index`. This downloads the latest `index-v1.zip` from the https://github.com/relaton/relaton-data-iho[relaton-data-iho] repository.
|
|
141
|
+
|
|
140
142
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to https://rubygems.org[rubygems.org].
|
|
141
143
|
|
|
142
144
|
== Contributing
|
data/Rakefile
CHANGED
|
@@ -4,3 +4,27 @@ require "rspec/core/rake_task"
|
|
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
|
5
5
|
|
|
6
6
|
task :default => :spec
|
|
7
|
+
|
|
8
|
+
namespace :spec do
|
|
9
|
+
desc "Download latest IHO index fixture from relaton-data-iho"
|
|
10
|
+
task :update_index do
|
|
11
|
+
require "net/http"
|
|
12
|
+
require "uri"
|
|
13
|
+
require_relative "lib/relaton/iho"
|
|
14
|
+
|
|
15
|
+
filename = "#{Relaton::Iho::INDEXFILE}.zip"
|
|
16
|
+
url = "https://raw.githubusercontent.com/relaton/relaton-data-iho/data-v2/\#{filename}"
|
|
17
|
+
dest = File.join(__dir__, "spec", "fixtures", filename)
|
|
18
|
+
|
|
19
|
+
puts "Downloading \#{url} ..."
|
|
20
|
+
uri = URI.parse(url)
|
|
21
|
+
response = Net::HTTP.get_response(uri)
|
|
22
|
+
|
|
23
|
+
if response.is_a?(Net::HTTPSuccess)
|
|
24
|
+
File.binwrite(dest, response.body)
|
|
25
|
+
puts "Updated \#{dest} (\#{response.body.bytesize} bytes)"
|
|
26
|
+
else
|
|
27
|
+
abort "Failed to download: HTTP \#{response.code}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -2,7 +2,7 @@ require "net/http"
|
|
|
2
2
|
|
|
3
3
|
module Relaton
|
|
4
4
|
module Iho
|
|
5
|
-
|
|
5
|
+
module Bibliography
|
|
6
6
|
ENDPOINT = "https://raw.githubusercontent.com/relaton/relaton-data-iho/refs/heads/data-v2/".freeze
|
|
7
7
|
|
|
8
8
|
class << self
|
|
@@ -14,12 +14,11 @@ module Relaton
|
|
|
14
14
|
# @return [RelatonIho::IhoBibliographicItem, nil] the IHO standard or nil if not found
|
|
15
15
|
#
|
|
16
16
|
def search(text, _year = nil, _opts = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
row = index.search(ref).min_by { |r| r[:id] }
|
|
17
|
+
pubid = text.is_a?(String) ? ::Pubid::Iho::Identifier.parse(text) : text
|
|
18
|
+
Util.info "Fetching from Relaton repository ...", key: pubid.to_s
|
|
19
|
+
row = index.search { |r| pubid_match?(r[:id], pubid) }.min_by { |r| row_version(r[:id]) }
|
|
21
20
|
unless row
|
|
22
|
-
Util.info "Not found.", key:
|
|
21
|
+
Util.info "Not found.", key: pubid.to_s
|
|
23
22
|
return
|
|
24
23
|
end
|
|
25
24
|
|
|
@@ -30,7 +29,8 @@ module Relaton
|
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
item = Relaton::Iho::Item.from_yaml resp.body
|
|
33
|
-
|
|
32
|
+
enrich_with_pubid(item, pubid)
|
|
33
|
+
Util.info "Found: `#{item.docidentifier.first.content}`", key: pubid.to_s
|
|
34
34
|
item.tap { |i| i.fetched = Date.today.to_s }
|
|
35
35
|
rescue SocketError, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
|
36
36
|
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
|
@@ -39,6 +39,31 @@ module Relaton
|
|
|
39
39
|
raise Relaton::RequestError, "Could not access #{uri}: #{e.message}"
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# Populate ext.structuredidentifier from the parsed Pubid when the
|
|
43
|
+
# fetched record doesn't already provide one. Maps `pubid.number`
|
|
44
|
+
# (with type prefix, e.g. `S-100`) -> docnumber, `pubid.part` -> part,
|
|
45
|
+
# `pubid.appendix` -> appendixid, `pubid.annex` -> annexid,
|
|
46
|
+
# `pubid.supplement` -> supplementid.
|
|
47
|
+
def enrich_with_pubid(item, pubid)
|
|
48
|
+
return if item.ext&.structuredidentifier&.any?
|
|
49
|
+
|
|
50
|
+
sid = StructuredIdentifier.new(
|
|
51
|
+
docnumber: pubid_docnumber(pubid),
|
|
52
|
+
part: pubid.part,
|
|
53
|
+
appendixid: (pubid.appendix if pubid.respond_to?(:appendix)),
|
|
54
|
+
annexid: (pubid.annex if pubid.respond_to?(:annex)),
|
|
55
|
+
supplementid: (pubid.supplement if pubid.respond_to?(:supplement)),
|
|
56
|
+
)
|
|
57
|
+
item.ext ||= Ext.new
|
|
58
|
+
item.ext.structuredidentifier = [sid]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# "S-100" rather than "100" — keeps the type prefix that distinguishes
|
|
62
|
+
# the IHO series (S/P/M/B/C). Matches spec/fixtures/iho_part.xml.
|
|
63
|
+
def pubid_docnumber(pubid)
|
|
64
|
+
pubid.to_s.sub(/^IHO\s/, "").split(/\s+/, 2).first
|
|
65
|
+
end
|
|
66
|
+
|
|
42
67
|
# @param ref [String] the IHO standard Code to look up (e..g "IHO B-11")
|
|
43
68
|
# @param year [String] the year the standard was published (optional)
|
|
44
69
|
#
|
|
@@ -51,6 +76,49 @@ module Relaton
|
|
|
51
76
|
def get(ref, year = nil, opts = {})
|
|
52
77
|
search(ref, year, opts)
|
|
53
78
|
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def index
|
|
83
|
+
Relaton::Index.find_or_create(
|
|
84
|
+
:iho,
|
|
85
|
+
url: "#{ENDPOINT}#{INDEXFILE}.zip",
|
|
86
|
+
file: "#{INDEXFILE}.yaml",
|
|
87
|
+
id_keys: %i[publisher number type version part appendix annex supplement],
|
|
88
|
+
pubid_class: ::Pubid::Iho::Identifier,
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def pubid_match?(row_id, query)
|
|
93
|
+
row_attrs = row_attributes(row_id)
|
|
94
|
+
return false unless row_attrs
|
|
95
|
+
|
|
96
|
+
query_attrs = query.to_h
|
|
97
|
+
# Subdivision keys (part/appendix/annex/supplement) use strict
|
|
98
|
+
# equality — a nil query must match a nil row (the umbrella),
|
|
99
|
+
# not an arbitrary subdivision under the same (number, version).
|
|
100
|
+
# Only :version stays nil-tolerant: an unqualified `IHO B-11`
|
|
101
|
+
# query is expected to find the latest edition.
|
|
102
|
+
row_attrs[:publisher] == query_attrs[:publisher] &&
|
|
103
|
+
row_attrs[:type] == query_attrs[:type] &&
|
|
104
|
+
row_attrs[:number] == query_attrs[:number] &&
|
|
105
|
+
(query_attrs[:version].nil? || row_attrs[:version].to_s == query_attrs[:version].to_s) &&
|
|
106
|
+
row_attrs[:part].to_s == query_attrs[:part].to_s &&
|
|
107
|
+
row_attrs[:appendix].to_s == query_attrs[:appendix].to_s &&
|
|
108
|
+
row_attrs[:annex].to_s == query_attrs[:annex].to_s &&
|
|
109
|
+
row_attrs[:supplement].to_s == query_attrs[:supplement].to_s
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def row_attributes(row_id)
|
|
113
|
+
return row_id.to_h if row_id.is_a?(::Pubid::Core::Identifier::Base)
|
|
114
|
+
return row_id if row_id.is_a?(Hash)
|
|
115
|
+
|
|
116
|
+
nil
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def row_version(row_id)
|
|
120
|
+
row_attributes(row_id)&.dig(:version).to_s
|
|
121
|
+
end
|
|
54
122
|
end
|
|
55
123
|
end
|
|
56
124
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Iho
|
|
3
|
+
class Docidentifier < Bib::Docidentifier
|
|
4
|
+
attr_reader :pubid
|
|
5
|
+
|
|
6
|
+
def initialize(attrs = {}, options = {})
|
|
7
|
+
pubid = attrs.is_a?(Hash) ? attrs.delete(:pubid) : nil
|
|
8
|
+
attrs[:content] ||= pubid.to_s if pubid
|
|
9
|
+
super
|
|
10
|
+
@pubid = pubid if pubid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def content=(value)
|
|
14
|
+
super
|
|
15
|
+
@pubid = ::Pubid::Iho::Identifier.parse(value) if value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_h
|
|
19
|
+
@pubid&.to_h || super
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def remove_part!
|
|
23
|
+
@pubid&.part = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def remove_date!
|
|
27
|
+
@pubid&.year = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_all_parts!
|
|
31
|
+
@pubid&.all_parts = true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/relaton/iho/ext.rb
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
require_relative "doctype"
|
|
2
2
|
require_relative "comment_period"
|
|
3
|
+
require_relative "structured_identifier"
|
|
3
4
|
|
|
4
5
|
module Relaton
|
|
5
6
|
module Iho
|
|
6
7
|
class Ext < Bib::Ext
|
|
7
8
|
attribute :doctype, Doctype, default: -> { Doctype.new(content: "standard") }
|
|
8
9
|
attribute :commentperiod, CommentPeriod
|
|
10
|
+
attribute :structuredidentifier, StructuredIdentifier,
|
|
11
|
+
collection: true, initialize_empty: true
|
|
9
12
|
|
|
10
13
|
xml do
|
|
11
14
|
map_element "commentperiod", to: :commentperiod
|
|
@@ -19,9 +19,20 @@ module Relaton
|
|
|
19
19
|
ret[:ext][:flavor] ||= flavor(ret)
|
|
20
20
|
ics_hash_to_bib ret
|
|
21
21
|
commentperiod_hash_to_bib ret
|
|
22
|
+
structuredidentifier_hash_to_bib ret
|
|
22
23
|
ret[:ext] = Ext.new(**ret[:ext])
|
|
23
24
|
end
|
|
24
25
|
|
|
26
|
+
def structuredidentifier_hash_to_bib(ret)
|
|
27
|
+
sid = ret.dig(:ext, :structuredidentifier) || ret[:structuredidentifier]
|
|
28
|
+
return unless sid
|
|
29
|
+
|
|
30
|
+
ret[:ext]&.delete(:structuredidentifier)
|
|
31
|
+
ret.delete(:structuredidentifier)
|
|
32
|
+
ret[:ext][:structuredidentifier] =
|
|
33
|
+
array(sid).map { |s| StructuredIdentifier.new(**s) }
|
|
34
|
+
end
|
|
35
|
+
|
|
25
36
|
def commentperiod_hash_to_bib(ret)
|
|
26
37
|
cp = ret.dig(:ext, :commentperiod) || ret[:commentperiod]
|
|
27
38
|
return unless cp
|
|
@@ -124,6 +135,10 @@ module Relaton
|
|
|
124
135
|
def create_relation(rel)
|
|
125
136
|
Relation.new(**rel)
|
|
126
137
|
end
|
|
138
|
+
|
|
139
|
+
def create_docid(**args)
|
|
140
|
+
Docidentifier.new(**args)
|
|
141
|
+
end
|
|
127
142
|
end
|
|
128
143
|
end
|
|
129
144
|
end
|
data/lib/relaton/iho/item.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative "item_data"
|
|
2
2
|
require_relative "ext"
|
|
3
|
+
require_relative "docidentifier"
|
|
3
4
|
|
|
4
5
|
module Relaton
|
|
5
6
|
module Iho
|
|
@@ -7,6 +8,8 @@ module Relaton
|
|
|
7
8
|
model ItemData
|
|
8
9
|
|
|
9
10
|
attribute :ext, Ext
|
|
11
|
+
attribute :docidentifier, Docidentifier, collection: true,
|
|
12
|
+
initialize_empty: true
|
|
10
13
|
end
|
|
11
14
|
end
|
|
12
15
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Iho
|
|
3
|
+
class StructuredIdentifier < Lutaml::Model::Serializable
|
|
4
|
+
attribute :docnumber, :string
|
|
5
|
+
attribute :part, :string
|
|
6
|
+
attribute :annexid, :string
|
|
7
|
+
attribute :appendixid, :string
|
|
8
|
+
attribute :supplementid, :string
|
|
9
|
+
|
|
10
|
+
xml do
|
|
11
|
+
root "structuredidentifier"
|
|
12
|
+
map_element "docnumber", to: :docnumber
|
|
13
|
+
map_element "part", to: :part
|
|
14
|
+
map_element "annexid", to: :annexid
|
|
15
|
+
map_element "appendixid", to: :appendixid
|
|
16
|
+
map_element "supplementid", to: :supplementid
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/relaton/iho/version.rb
CHANGED
data/lib/relaton/iho.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require "relaton/bib"
|
|
2
2
|
require "relaton/index"
|
|
3
|
+
require "pubid/iho"
|
|
3
4
|
require_relative "iho/version"
|
|
4
5
|
require_relative "iho/util"
|
|
6
|
+
require_relative "iho/docidentifier"
|
|
5
7
|
require_relative "iho/item"
|
|
6
8
|
require_relative "iho/bibitem"
|
|
7
9
|
require_relative "iho/bibdata"
|
|
@@ -9,7 +11,7 @@ require_relative "iho/bibliography"
|
|
|
9
11
|
|
|
10
12
|
module Relaton
|
|
11
13
|
module Iho
|
|
12
|
-
INDEXFILE = "index-
|
|
14
|
+
INDEXFILE = "index-v2".freeze
|
|
13
15
|
|
|
14
16
|
class Error < StandardError; end
|
|
15
17
|
|
data/relaton_iho.gemspec
CHANGED
|
@@ -22,7 +22,8 @@ Gem::Specification.new do |s|
|
|
|
22
22
|
s.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
|
|
23
23
|
|
|
24
24
|
s.add_dependency "base64"
|
|
25
|
-
s.add_dependency "
|
|
25
|
+
s.add_dependency "pubid-iho", "~> 1.15.15"
|
|
26
|
+
s.add_dependency "relaton-bib", "~> 2.0.0"
|
|
26
27
|
s.add_dependency "relaton-core", "~> 0.0.13"
|
|
27
28
|
s.add_dependency "relaton-index", "~> 0.2.0"
|
|
28
29
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: relaton-iho
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -23,20 +23,34 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: pubid-iho
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.15.15
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 1.15.15
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: relaton-bib
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
29
43
|
requirements:
|
|
30
44
|
- - "~>"
|
|
31
45
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 2.0.0
|
|
46
|
+
version: 2.0.0
|
|
33
47
|
type: :runtime
|
|
34
48
|
prerelease: false
|
|
35
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
50
|
requirements:
|
|
37
51
|
- - "~>"
|
|
38
52
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 2.0.0
|
|
53
|
+
version: 2.0.0
|
|
40
54
|
- !ruby/object:Gem::Dependency
|
|
41
55
|
name: relaton-core
|
|
42
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -93,6 +107,7 @@ files:
|
|
|
93
107
|
- lib/relaton/iho/bibitem.rb
|
|
94
108
|
- lib/relaton/iho/bibliography.rb
|
|
95
109
|
- lib/relaton/iho/comment_period.rb
|
|
110
|
+
- lib/relaton/iho/docidentifier.rb
|
|
96
111
|
- lib/relaton/iho/doctype.rb
|
|
97
112
|
- lib/relaton/iho/ext.rb
|
|
98
113
|
- lib/relaton/iho/hash_parser_v1.rb
|
|
@@ -101,6 +116,7 @@ files:
|
|
|
101
116
|
- lib/relaton/iho/item_data.rb
|
|
102
117
|
- lib/relaton/iho/processor.rb
|
|
103
118
|
- lib/relaton/iho/relation.rb
|
|
119
|
+
- lib/relaton/iho/structured_identifier.rb
|
|
104
120
|
- lib/relaton/iho/util.rb
|
|
105
121
|
- lib/relaton/iho/version.rb
|
|
106
122
|
- relaton_iho.gemspec
|