relaton-nist 1.12.5 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c73a4a75166a362d34e2d1a4bec088d74863cf1ac9a4eee0798cfa84cbceca6
4
- data.tar.gz: 398bd9b074c7c10da66c86047e617e7b643ea6cc3e45f1daa6fdd6f43d38bb4c
3
+ metadata.gz: c997f338c657a003a0bff7e75b650f59b86d4a72026a0b12734357bc48c10cdc
4
+ data.tar.gz: 5d76af2d37037bb027f9875180bbcc967ca133260eb4a5494112fe81cccf5e04
5
5
  SHA512:
6
- metadata.gz: 7695197e53d2d8b8b2048f034c6d47db2ce293f7f8dedafacefae8efb4ad85ed96169f5b317957a228b32bfa1e9a8899b80238aa8be594edd94e89619c9fbb51
7
- data.tar.gz: 1b2eb51d32d0b0eb9456242e5727b891468509a55cdc2ce2251fa84857b83d6d29966bb3799557672da7cabc126949f0cc18d6581cb9464caa38293a317a7265
6
+ metadata.gz: 5971a572c9a7a5aefb4087f96787255687195c3e0cc75a49f740b57af1bb05fa48f56c2bd721cbb4b5aa7e5178cb93048c97a8782d152b4b040dd3158129ba14
7
+ data.tar.gz: f266510c36ce07666a74b9881e439df01067f6baee05e03c267ce3754bef5dcf24b7391082a4fdc1d8122121f17b1fc30e3ba8377dadd86692ff80cd8efa962d
data/grammars/biblio.rng CHANGED
@@ -225,9 +225,9 @@
225
225
  <zeroOrMore>
226
226
  <ref name="forename"/>
227
227
  </zeroOrMore>
228
- <zeroOrMore>
229
- <ref name="initial"/>
230
- </zeroOrMore>
228
+ <optional>
229
+ <ref name="formatted-initials"/>
230
+ </optional>
231
231
  <ref name="surname"/>
232
232
  <zeroOrMore>
233
233
  <ref name="addition"/>
@@ -247,8 +247,8 @@
247
247
  <ref name="LocalizedString"/>
248
248
  </element>
249
249
  </define>
250
- <define name="initial">
251
- <element name="initial">
250
+ <define name="formatted-initials">
251
+ <element name="formatted-initials">
252
252
  <ref name="LocalizedString"/>
253
253
  </element>
254
254
  </define>
@@ -264,6 +264,9 @@
264
264
  </define>
265
265
  <define name="forename">
266
266
  <element name="forename">
267
+ <optional>
268
+ <attribute name="initial"/>
269
+ </optional>
267
270
  <ref name="LocalizedString"/>
268
271
  </element>
269
272
  </define>
data/grammars/isodoc.rng CHANGED
@@ -69,6 +69,17 @@
69
69
  </zeroOrMore>
70
70
  </element>
71
71
  </define>
72
+ <define name="AdmonitionType">
73
+ <choice>
74
+ <value>warning</value>
75
+ <value>note</value>
76
+ <value>tip</value>
77
+ <value>important</value>
78
+ <value>caution</value>
79
+ <value>statement</value>
80
+ <value>editorial</value>
81
+ </choice>
82
+ </define>
72
83
  <define name="index">
73
84
  <element name="index">
74
85
  <optional>
@@ -1274,7 +1285,12 @@
1274
1285
  </define>
1275
1286
  <define name="span">
1276
1287
  <element name="span">
1277
- <attribute name="class"/>
1288
+ <optional>
1289
+ <attribute name="class"/>
1290
+ </optional>
1291
+ <optional>
1292
+ <attribute name="style"/>
1293
+ </optional>
1278
1294
  <oneOrMore>
1279
1295
  <ref name="TextElement"/>
1280
1296
  </oneOrMore>
@@ -2493,6 +2509,16 @@
2493
2509
  <text/>
2494
2510
  </element>
2495
2511
  </optional>
2512
+ <optional>
2513
+ <element name="amendment">
2514
+ <text/>
2515
+ </element>
2516
+ </optional>
2517
+ <optional>
2518
+ <element name="corrigendum">
2519
+ <text/>
2520
+ </element>
2521
+ </optional>
2496
2522
  <optional>
2497
2523
  <element name="language">
2498
2524
  <text/>
@@ -157,13 +157,13 @@ module RelatonNist
157
157
  # @return [RelatonBib::FullName] full name object
158
158
  #
159
159
  def fullname(person, doc)
160
- forename, initial = forename_initial(person, doc)
160
+ forename, initials = forename_initial(person, doc)
161
161
  surname = localized_string person.at("surname").text, doc
162
162
  ident = person.xpath("ORCID").map do |id|
163
163
  RelatonBib::PersonIdentifier.new "orcid", id.text
164
164
  end
165
165
  RelatonBib::FullName.new(surname: surname, forename: forename,
166
- initial: initial, identifier: ident)
166
+ initials: initials, identifier: ident)
167
167
  end
168
168
 
169
169
  #
@@ -174,17 +174,33 @@ module RelatonNist
174
174
  #
175
175
  # @return [Array<Array<RelatonBib::LocalizedString>>] forename and initials
176
176
  #
177
- def forename_initial(person, doc)
178
- forename = []
179
- initial = []
177
+ def forename_initial(person, doc) # rubocop:disable Metrics/MethodLength
178
+ fnames = []
180
179
  fname = person.at("given_name")&.text
181
180
  if fname
182
181
  if /^(?<inits>(?:\w[.\s]+|[A-Z]{1,2}$)+)$/ =~ fname
183
- inits.split(/[.\s]*/).each { |i| initial << localized_string(i, doc) }
184
- else forename << localized_string(fname, doc)
182
+ ints = inits.split(/[.\s]*/)
183
+ fnames << forename(doc, fname, ints.shift)
184
+ ints.each { |i| fnames << forename(doc, nil, i) }
185
+ else fnames << forename(doc, fname)
185
186
  end
186
187
  end
187
- [forename, initial]
188
+ [fnames, localized_string(inits, doc)]
189
+ end
190
+
191
+ #
192
+ # Create forename object
193
+ #
194
+ # @param [Nokogiri::XML::Element] doc document element
195
+ # @param [String, nil] cnt forename content
196
+ # @param [String, nil] init initial content
197
+ #
198
+ # @return [RelatonBib::Forename] forename object
199
+ #
200
+ def forename(doc, cnt, init = nil)
201
+ RelatonBib::Forename.new(
202
+ content: cnt, language: doc["language"], script: "Latn", initial: init,
203
+ )
188
204
  end
189
205
 
190
206
  #
@@ -5,13 +5,20 @@ module RelatonNist
5
5
  class Hit < RelatonBib::Hit
6
6
  attr_writer :fetch
7
7
 
8
+ #
8
9
  # Parse page.
9
- # @return [RelatonNist::NistBliographicItem]
10
+ #
11
+ # @return [RelatonNist::NistBliographicItem] bibliographic item
12
+ #
10
13
  def fetch
11
14
  @fetch ||= Scrapper.parse_page @hit
12
15
  end
13
16
 
14
- # @return [Iteger]
17
+ #
18
+ # Calculate sorting weigth of hit by series, code, title, addendum, and status
19
+ #
20
+ # @return [Iteger] sorting weigth
21
+ #
15
22
  def sort_value # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
16
23
  @sort_value ||= begin
17
24
  sort_phrase = [hit[:series], hit[:code], hit[:title]].join " "
@@ -7,7 +7,7 @@ require "addressable/uri"
7
7
  require "open-uri"
8
8
 
9
9
  module RelatonNist
10
- # Page of hit collection.
10
+ # Hit collection.
11
11
  class HitCollection < RelatonBib::HitCollection
12
12
  DOMAIN = "https://csrc.nist.gov"
13
13
  PUBS_EXPORT = URI.join(DOMAIN, "/CSRC/media/feeds/metanorma/pubs-export")
@@ -15,17 +15,37 @@ module RelatonNist
15
15
  DATAFILE = File.expand_path "pubs-export.zip", DATAFILEDIR
16
16
  GHNISTDATA = "https://raw.githubusercontent.com/relaton/relaton-data-nist/main/data/"
17
17
 
18
+ #
19
+ # Create hits collection instance and search hits
20
+ #
21
+ # @param [Hash] opts options
22
+ # @option opts [String] :stage stage of document
23
+ #
24
+ # @return [RelatonNist::HitCollection] hits collection
25
+ #
18
26
  def self.search(text, year = nil, opts = {})
19
27
  new(text, year).search(opts)
20
28
  end
21
29
 
30
+ #
31
+ # Search nits in JSON file or GitHub repo
32
+ #
33
+ # @param [Hash] opts options
34
+ # @option opts [String] :stage stage of document
35
+ #
36
+ # @return [RelatonNist::HitCollection] hits collection
37
+ #
22
38
  def search(opts)
23
39
  @array = from_json(**opts)
24
40
  @array = from_ga unless @array.any?
25
41
  sort_hits!
26
42
  end
27
43
 
28
- # @return [Array<RelatonNist::Hit>]
44
+ #
45
+ # Filter hits by reference's parts
46
+ #
47
+ # @return [Array<RelatonNist::Hit>] hits
48
+ #
29
49
  def search_filter # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
30
50
  @array.select do |item|
31
51
  %r{
@@ -53,6 +73,11 @@ module RelatonNist
53
73
 
54
74
  private
55
75
 
76
+ #
77
+ # Parse reference parts
78
+ #
79
+ # @return [Hash] reference parts
80
+ #
56
81
  def refparts # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
57
82
  @refparts ||= {
58
83
  perfix: match(/^(NIST|NBS)\s?/, text),
@@ -71,10 +96,23 @@ module RelatonNist
71
96
  }
72
97
  end
73
98
 
99
+ #
100
+ # Match regex to reference
101
+ #
102
+ # @param [Regexp] regex regex
103
+ # @param [String] code reference
104
+ #
105
+ # @return [String, nil] matched string
106
+ #
74
107
  def match(regex, code)
75
108
  regex.match(code)&.to_s
76
109
  end
77
110
 
111
+ #
112
+ # Generate reference from parts
113
+ #
114
+ # @return [String] reference
115
+ #
78
116
  def full_ref # rubocop:disable Metrics/AbcSize
79
117
  @full_ref ||= begin
80
118
  ref = "#{refparts[:perfix]}#{refparts[:series]} #{refparts[:code]}"
@@ -84,9 +122,16 @@ module RelatonNist
84
122
  end
85
123
  end
86
124
 
125
+ #
126
+ # Return short version of ID part with removed "-" or convert long version to short.
127
+ # Converts "pt-1" to "pt1" and "Part 1" to "pt1", "v-1" to "v1" and "Vol. 1" to "v1",
128
+ # "ver-1" to "ver1" and "Ver. 1" to "ver1", "r-1" to "r1" and "Rev. 1" to "r1".
129
+ #
87
130
  # @param short [String]
88
131
  # @param long [String]
132
+ #
89
133
  # @return [String, nil]
134
+ #
90
135
  def long_to_short(short, long)
91
136
  return short.sub(/-/, "") if short
92
137
  return unless long
@@ -94,6 +139,11 @@ module RelatonNist
94
139
  long.sub(/Part\s/, "pt").sub(/Vol\.\s/, "v").sub(/Rev\.\s/, "r").sub(/(Ver\.|Version)\s/, "ver")
95
140
  end
96
141
 
142
+ #
143
+ # Sort hits by sort_value and release date
144
+ #
145
+ # @return [self] sorted hits collection
146
+ #
97
147
  def sort_hits!
98
148
  @array.sort! do |a, b|
99
149
  if a.sort_value == b.sort_value
@@ -105,7 +155,14 @@ module RelatonNist
105
155
  self
106
156
  end
107
157
 
108
- def from_ga # rubocop:disable Metrics/AbcSize
158
+ #
159
+ # Get hit from GitHub repo
160
+ #
161
+ # @return [Array<RelatonNist::Hit>] hits
162
+ #
163
+ # @raise [OpenURI::HTTPError] if GitHub repo is not available
164
+ #
165
+ def from_ga # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
109
166
  ref = full_ref
110
167
  fn = ref.gsub(%r{[/\s:.]}, "_").upcase
111
168
  yaml = OpenURI.open_uri "#{GHNISTDATA}#{fn}.yaml"
@@ -120,9 +177,14 @@ module RelatonNist
120
177
  raise e
121
178
  end
122
179
 
180
+ #
123
181
  # Fetches data form json
124
- # @param stage [String]
125
- # @return [Array<RelatonNist::Hit>]
182
+ #
183
+ # @param opts [Hash] options
184
+ # @option opts [String] :stage stage of document
185
+ #
186
+ # @return [Array<RelatonNist::Hit>] hits
187
+ #
126
188
  def from_json(**opts)
127
189
  select_data(**opts).map do |h|
128
190
  /(?<series>(?<=-)\w+$)/ =~ h["series"]
@@ -134,8 +196,14 @@ module RelatonNist
134
196
  end
135
197
  end
136
198
 
137
- # @param stage [String]
138
- # @return [Array<Hach>]
199
+ #
200
+ # Select data from json
201
+ #
202
+ # @param opts [Hash] options
203
+ # @option opts [String] :stage stage of document
204
+ #
205
+ # @return [Array<Hash>] selected data
206
+ #
139
207
  def select_data(**opts) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity
140
208
  ref = "#{refparts[:series]} #{refparts[:code]}"
141
209
  d = Date.strptime year, "%Y" if year
@@ -152,9 +220,14 @@ module RelatonNist
152
220
  end
153
221
  end
154
222
 
155
- # @param doc [Hash]
223
+ #
224
+ # Check if issued date is match to year
225
+ #
226
+ # @param doc [Hash] document's metadata
156
227
  # @param date [Date] first day of year
157
- # @return [TrueClass, FalseClass]
228
+ #
229
+ # @return [Boolean]
230
+ #
158
231
  def match_year?(doc, date)
159
232
  return true unless year
160
233
 
@@ -162,8 +235,11 @@ module RelatonNist
162
235
  idate.between? date, date.next_year.prev_day
163
236
  end
164
237
 
238
+ #
165
239
  # Fetches json data form server
166
- # @return [Hash]
240
+ #
241
+ # @return [Array<Hash>] json data
242
+ #
167
243
  def data
168
244
  ctime = File.ctime DATAFILE if File.exist? DATAFILE
169
245
  if !ctime || ctime.to_date < Date.today || File.size(DATAFILE).zero?
@@ -172,9 +248,11 @@ module RelatonNist
172
248
  unzip
173
249
  end
174
250
 
251
+ #
175
252
  # Fetch data form server and save it to file
176
253
  #
177
- # @prarm ctime [Time, NilClass]
254
+ # @prarm ctime [Time, nil] file creation time
255
+ #
178
256
  def fetch_data(ctime)
179
257
  if !ctime || ctime < OpenURI.open_uri("#{PUBS_EXPORT}.meta").last_modified
180
258
  @data = nil
@@ -184,9 +262,11 @@ module RelatonNist
184
262
  end
185
263
  end
186
264
 
265
+ #
187
266
  # upack zip file
188
267
  #
189
- # @return [Hash]
268
+ # @return [Array<Hash>] json data
269
+ #
190
270
  def unzip
191
271
  return @data if @data
192
272
 
@@ -11,8 +11,13 @@ require "relaton_nist/hash_converter"
11
11
  module RelatonNist
12
12
  class NistBibliography
13
13
  class << self
14
- # @param text [String]
15
- # @return [RelatonNist::HitCollection]
14
+ #
15
+ # Search NIST docuemnts by reference
16
+ #
17
+ # @param text [String] reference
18
+ #
19
+ # @return [RelatonNist::HitCollection] search result
20
+ #
16
21
  def search(text, year = nil, opts = {})
17
22
  ref = text.sub(/^NIST\sIR/, "NISTIR")
18
23
  HitCollection.search ref, year, opts
@@ -20,15 +25,18 @@ module RelatonNist
20
25
  raise RelatonBib::RequestError, e.message
21
26
  end
22
27
 
28
+ #
29
+ # Get NIST document by reference
30
+ #
23
31
  # @param code [String] the NIST standard Code to look up (e..g "8200")
24
32
  # @param year [String] the year the standard was published (optional)
25
33
  #
26
34
  # @param opts [Hash] options
27
- # @option opts [TrueClass, FalseClass] :all_parts restricted to all parts
35
+ # @option opts [Boolean] :all_parts restricted to all parts
28
36
  # if all-parts reference is required
29
- # @option opts [TrueClass, FalseClass] :bibdata
30
37
  #
31
- # @return [String] Relaton XML serialisation of reference
38
+ # @return [RelatonNist::NistBibliographicItem, nil] bibliographic item
39
+ #
32
40
  def get(code, year = nil, opts = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
33
41
  return fetch_ref_err(code, year, []) if code.match?(/\sEP$/)
34
42
 
@@ -61,6 +69,18 @@ module RelatonNist
61
69
 
62
70
  private
63
71
 
72
+ #
73
+ # Get NIST document by reference
74
+ #
75
+ # @param [String] code reference
76
+ # @param [String] year year
77
+ # @param [Hash] opts options
78
+ # @option opts [Date] :issued_date issued date
79
+ # @option opts [Date] :updated_date updated date
80
+ # @option opts [String] :stage stage
81
+ #
82
+ # @return [RelatonNist::NistBibliographicItem, nil] bibliographic item
83
+ #
64
84
  def nistbib_get(code, year, opts)
65
85
  result = nistbib_search_filter(code, year, opts) || (return nil)
66
86
  ret = nistbib_results_filter(result, year, opts)
@@ -72,6 +92,7 @@ module RelatonNist
72
92
  end
73
93
  end
74
94
 
95
+ #
75
96
  # Sort through the results from RelatonNist, fetching them three at a time,
76
97
  # and return the first result that matches the code,
77
98
  # matches the year (if provided), and which # has a title (amendments do not).
@@ -80,11 +101,12 @@ module RelatonNist
80
101
  # If no match, returns any years which caused mismatch, for error reporting
81
102
  #
82
103
  # @param opts [Hash] options
83
- # @option opts [Time] :issued_date
84
- # @option opts [Time] :issued_date
85
- # @option opts [String] :stage
104
+ # @option opts [Date] :issued_date issued date
105
+ # @option opts [Date] :issued_date issued date
106
+ # @option opts [String] :stage stage
107
+ #
108
+ # @return [Hash] result
86
109
  #
87
- # @return [Hash]
88
110
  def nistbib_results_filter(result, year, opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
89
111
  missed_years = []
90
112
  iter = /\w+(?=PD)|(?<=PD-)\w+/.match(opts[:stage])&.to_s
@@ -119,9 +141,14 @@ module RelatonNist
119
141
  { years: missed_years }
120
142
  end
121
143
 
122
- # @param hits [RelatonNist::HitCollection]
123
- # @param threads [Integer]
124
- # @return [Array<RelatonNist::NistBibliographicItem>]
144
+ #
145
+ # Fetch pages for all the hits in parallel
146
+ #
147
+ # @param hits [RelatonNist::HitCollection] hits
148
+ # @param threads [Integer] number of threads
149
+ #
150
+ # @return [Array<RelatonNist::NistBibliographicItem>] bibliographic items
151
+ #
125
152
  def fetch_pages(hits, threads)
126
153
  workers = RelatonBib::WorkersPool.new threads
127
154
  workers.worker { |w| { i: w[:i], hit: w[:hit].fetch } }
@@ -130,16 +157,31 @@ module RelatonNist
130
157
  workers.result.sort_by { |a| a[:i] }.map { |x| x[:hit] }
131
158
  end
132
159
 
133
- # @param code [String]
134
- # @param year [String, nil]
135
- # @param opts [Hash]
136
- # @return [RelatonNist::HitCollection]
160
+ #
161
+ # Get search results and filter them by code and year
162
+ #
163
+ # @param code [String] reference
164
+ # @param year [String, nil] year
165
+ # @param opts [Hash] options
166
+ # @option opts [String] :stage stage
167
+ #
168
+ # @return [RelatonNist::HitCollection] hits collection
169
+ #
137
170
  def nistbib_search_filter(code, year, opts)
138
171
  warn "[relaton-nist] (\"#{code}\") fetching..."
139
172
  result = search(code, year, opts)
140
173
  result.search_filter
141
174
  end
142
175
 
176
+ #
177
+ # Outputs warning message if no match found
178
+ #
179
+ # @param [String] code reference
180
+ # @param [String, nil] year year
181
+ # @param [Array<String>] missed_years missed years
182
+ #
183
+ # @return [nil] nil
184
+ #
143
185
  def fetch_ref_err(code, year, missed_years) # rubocop:disable Metrics/MethodLength
144
186
  id = year ? "#{code}:#{year}" : code
145
187
  warn "[relaton-nist] WARNING: no match found online for #{id}. " \
@@ -1,3 +1,3 @@
1
1
  module RelatonNist
2
- VERSION = "1.12.5".freeze
2
+ VERSION = "1.13.0".freeze
3
3
  end
data/relaton_nist.gemspec CHANGED
@@ -32,6 +32,6 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "vcr"
33
33
  spec.add_development_dependency "webmock"
34
34
 
35
- spec.add_dependency "relaton-bib", "~> 1.12.0"
35
+ spec.add_dependency "relaton-bib", "~> 1.13.0"
36
36
  spec.add_dependency "rubyzip"
37
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-nist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.5
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-23 00:00:00.000000000 Z
11
+ date: 2022-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: equivalent-xml
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.12.0
131
+ version: 1.13.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 1.12.0
138
+ version: 1.13.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubyzip
141
141
  requirement: !ruby/object:Gem::Requirement