relaton-nist 1.16.3 → 1.16.4

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: b00f5d1fb998afa9409df9108f6336cf067fc41faef13e8aca3a95cc8b289596
4
- data.tar.gz: 17f09df20a20798c1a56b5b7b887d7be9a8509e3a948b731603cbd95e684346e
3
+ metadata.gz: 9584f82c13f12da662266b2de0e11eb37241a6b3c4994d28720af44bdb713632
4
+ data.tar.gz: 1d14d47f043644e96cd42a8419117e12111623e5e80a7a2cb37ac6c1420d37c1
5
5
  SHA512:
6
- metadata.gz: 1dfc55cfa95ad85bf38a3a582d5d92fea954f7fd7e66537d59d78f672efd798f10bb1bed8ee804c4c9b062017fa7202edd38295b9456c990368883bb77861436
7
- data.tar.gz: 0e3b65872354a4c48dfd1f752ec160d3d2bdd47bafa9e678a3a5e200189589ce1e09b25e17df7c05bf6f643290f10ad3925bd9efb415525cf1c91894d3c6f92a
6
+ metadata.gz: 1d86cd19ea38a1743044ce99e28c6c5c0adc4805d5c45d6145ff4f724b10a9f9115a495cd226514fbd66e2213dce3ba807baddf3275528ae438917c36f3784a8
7
+ data.tar.gz: 0c8f579f4b9eca0402d1a28c986ad188d72b2dac57a8f4cc92d18a17ea235d7fe7ebd03a3f38dcd17e91496adc595ce347b8a1c73f449d48008e54655c5ce9e1
data/README.adoc CHANGED
@@ -89,10 +89,12 @@ end
89
89
 
90
90
  [source,ruby]
91
91
  ----
92
- hit_collection = RelatonNist::NistBibliography.search("8200")
93
- => <RelatonNist::HitCollection:0x007fc069d19da0 @ref=8200 @fetched=false>
92
+ hit_collection = RelatonNist::NistBibliography.search("NISTIR 8200")
93
+ [relaton-nist] (NIST IR 8200) Fetching from csrc.nist.gov ...
94
+ [relaton-nist] (NIST IR 8200) Fetching from Relaton repository ...
95
+ => <RelatonNist::HitCollection:0x00000000004b28 @ref=NIST IR 8200 @fetched=false>
94
96
 
95
- item = hit_collection[1].fetch
97
+ item = hit_collection[0].fetch
96
98
  => #<RelatonNist::NistBibliographicItem:0x007fc049aa6778
97
99
  ...
98
100
  ----
@@ -101,9 +103,9 @@ item = hit_collection[1].fetch
101
103
  [source,ruby]
102
104
  ----
103
105
  item.to_xml
104
- => "<bibitem id="SP800-160Vol.1Ver.1Rev.1" type="standard" schema-version="v1.2.1">
105
- <fetched>2022-12-05</fetched>
106
- <title format="text/plain" language="en" script="Latn">Engineering Trustworthy Secure Systems</title>
106
+ => "<bibitem id="NISTIR8200" type="standard" schema-version="v1.2.4">
107
+ <fetched>2023-10-16</fetched>
108
+ <title format="text/plain" language="en" script="Latn">Interagency report on the status of international cybersecurity standardization for the internet of things (IoT)</title>
107
109
  ...
108
110
  <bibitem>"
109
111
  ----
@@ -111,9 +113,9 @@ With argument `bibdata: true` it outputs XML wrapped by `bibdata` element and ad
111
113
  [source,ruby]
112
114
  ----
113
115
  item.to_xml bibdata: true
114
- => "<bibdata type="standard" schema-version="v1.2.1">
115
- <fetched>2022-12-05</fetched>
116
- <title format="text/plain" language="en" script="Latn">Engineering Trustworthy Secure Systems</title>
116
+ => "<bibdata type="standard" schema-version="v1.2.4">
117
+ <fetched>2023-10-16</fetched>
118
+ <title format="text/plain" language="en" script="Latn">Interagency report on the status of international cybersecurity standardization for the internet of things (IoT)</title>
117
119
  ...
118
120
  <ext schema-version="v1.0.0">
119
121
  <doctype>standard</doctype>
@@ -124,9 +126,10 @@ item.to_xml bibdata: true
124
126
  === Get code, and year
125
127
  [source,ruby]
126
128
  ----
127
- RelatonNist::NistBibliography.get("NIST IR 8200", "2018", {})
128
- [relaton-nist] (NIST IR 8200) fetching...
129
- [relaton-nist] (NIST IR 8200) found `NIST IR 8200`
129
+ RelatonNist::NistBibliography.get("NIST IR 8200", "2018")
130
+ [relaton-nist] (NIST SP 8200:2018) Fetching from csrc.nist.gov ...
131
+ [relaton-nist] (NIST IR 8200:2018) Fetching from Relaton repository...
132
+ [relaton-nist] (NIST IR 8200:2018) Found: `NIST IR 8200`
130
133
  => #<RelatonNist::NistBibliographicItem:0x00007fab74a572c0
131
134
  ...
132
135
  ----
@@ -153,10 +156,10 @@ NIST FIPS {docnumber}
153
156
  ----
154
157
  [source,ruby]
155
158
  ----
156
- RelatonNist::NistBibliography.get("SP 800-205 (February 2019) (PD)")
157
- [relaton-nist] (SP 800-205) fetching...
158
- [relaton-nist] (SP 800-205) found `SP 800-205 (Draft)`
159
- => #<RelatonNist::NistBibliographicItem:0x007fc059934768
159
+ RelatonNist::NistBibliography.get("NIST SP 800-205 (February 2019) (IPD)")
160
+ [relaton-nist] (NIST SP 800-205) Fetching from csrc.nist.gov ...
161
+ [relaton-nist] (NIST SP 800-205) Found: `NIST SP 800-205 (Draft)`
162
+ => #<RelatonNist::NistBibliographicItem:0x00000001105afdc8
160
163
  ...
161
164
  ----
162
165
 
@@ -172,22 +175,22 @@ Referehces can contain optional parameters `{ptN}{vN}{verN}{rN}{/Add}`:
172
175
  [source,ruby]
173
176
  ----
174
177
  item = RelatonNist::NistBibliography.get 'NIST SP 800-67r1'
175
- [relaton-nist] (NIST SP 800-67r1) fetching...
176
- [relaton-nist] (NIST SP 800-67r1) found `SP 800-67 Rev. 1`
177
- => #<RelatonNist::NistBibliographicItem:0x00007fab748ae978
178
+ [relaton-nist] (NIST SP 800-67r1) Fetching from csrc.nist.gov ...
179
+ [relaton-nist] (NIST SP 800-67r1) Found: `NIST SP 800-67 Rev. 1`
180
+ => #<RelatonNist::NistBibliographicItem:0x00000001105acd08
178
181
  ...
179
182
 
180
183
  item.docidentifier.first.id
181
- => "SP 800-67 Rev. 1"
184
+ => "NIST SP 800-67 Rev. 1"
182
185
 
183
- item = RelatonNist::NistBibliography.get 'SP 800-38A/Add'
184
- [relaton-nist] (SP 800-38A/Add) fetching...
185
- [relaton-nist] (SP 800-38A/Add) found `SP 800-38A-Add`
186
- => #<RelatonNist::NistBibliographicItem:0x007fd88c21d880
186
+ item = RelatonNist::NistBibliography.get 'NIST SP 800-38A/Add'
187
+ [relaton-nist] (NIST SP 800-38A/Add) Fetching from csrc.nist.gov ...
188
+ [relaton-nist] (NIST SP 800-38A/Add) Found: `NIST SP 800-38A-Add`
189
+ => #<RelatonNist::NistBibliographicItem:0x00000001105abf48
187
190
  ...
188
191
 
189
192
  item.docidentifier.first.id
190
- => "SP 800-38A-Add"
193
+ => "NIST SP 800-38A-Add"
191
194
  ----
192
195
 
193
196
  === Typed links
@@ -197,8 +200,12 @@ NIST documents may have `src` and `doi` link types.
197
200
  [source,ruby]
198
201
  ----
199
202
  item.link
200
- => [#<RelatonBib::TypedUri:0x00007f901971dc10 @content=#<Addressable::URI:0x62c URI:https://csrc.nist.gov/publications/detail/sp/800-67/rev-2/final>, @type="src">,
201
- #<RelatonBib::TypedUri:0x00007f901971d6e8 @content=#<Addressable::URI:0x640 URI:https://doi.org/10.6028/NIST.SP.800-67r2>, @type="doi">]
203
+ => [#<RelatonBib::TypedUri:0x0000000111087a98
204
+ @content=#<Addressable::URI:0x8c0 URI:https://csrc.nist.gov/pubs/sp/800/38/a/sup/final>,
205
+ @language=nil,
206
+ @script=nil,
207
+ @type="src">,
208
+ #<RelatonBib::TypedUri:0x00000001110879a8 @content=#<Addressable::URI:0x8d4 URI:https://doi.org/10.6028/NIST.SP.800-38A-Add>, @language=nil, @script=nil, @type="doi">]
202
209
  ----
203
210
 
204
211
  === Create bibliographic item from YAML
@@ -12,6 +12,9 @@ module RelatonNist
12
12
  GHNISTDATA = "https://raw.githubusercontent.com/relaton/relaton-data-nist/main/"
13
13
  INDEX_FILE = "index-v1.yaml"
14
14
 
15
+ attr_reader :reference
16
+ attr_accessor :array
17
+
15
18
  #
16
19
  # @param [String] text reference
17
20
  # @param [String, nil] year reference
@@ -20,6 +23,7 @@ module RelatonNist
20
23
  #
21
24
  def initialize(text, year = nil, opts = {})
22
25
  super text, year
26
+ @reference = year && !text.match?(/:\d{4}$/) ? "#{text}:#{year}" : text
23
27
  @opts = opts
24
28
  end
25
29
 
@@ -54,16 +58,21 @@ module RelatonNist
54
58
  # @return [Array<RelatonNist::Hit>] hits
55
59
  #
56
60
  def search_filter # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength
57
- @array.select do |item|
61
+ arr = @array.select do |item|
58
62
  parts = doi_parts(item.hit[:json]) || code_parts(item.hit[:code])
63
+ iteration = item.hit.dig(:json, "iteration")
64
+ draft = parts[:draft] || (!iteration.nil? && iteration.match?(/\wpd/i))
59
65
  refparts[:code] && [parts[:series], item.hit[:series]].include?(refparts[:series]) &&
60
66
  refparts[:code].casecmp(parts[:code].upcase).zero? &&
61
67
  refparts[:prt] == parts[:prt] &&
62
68
  (refparts[:vol].nil? || refparts[:vol] == parts[:vol]) &&
63
69
  (refparts[:ver].nil? || refparts[:ver] == parts[:ver]) &&
64
70
  (refparts[:rev].nil? || refparts[:rev] == parts[:rev]) &&
65
- refparts[:draft] == parts[:draft] && refparts[:add] == parts[:add]
71
+ refparts[:draft] == draft && refparts[:add] == parts[:add]
66
72
  end
73
+ dup = self.dup
74
+ dup.array = arr
75
+ dup
67
76
  end
68
77
 
69
78
  private
@@ -99,7 +108,7 @@ module RelatonNist
99
108
  ver: match(/v(?:er)?(?<val>[\d.]+)/, id),
100
109
  rev: match(/r(?<val>\d+)/, id),
101
110
  add: match(/-Add(?<val>\d*)/, id),
102
- draft: !match(/\.ipd/, id).nil?,
111
+ draft: !match(/\.ipd|-draft/, id).nil?,
103
112
  }
104
113
  end
105
114
 
@@ -181,7 +190,10 @@ module RelatonNist
181
190
  # @raise [OpenURI::HTTPError] if GitHub repo is not available
182
191
  #
183
192
  def from_ga # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
193
+ Util.warn "(#{@reference}) Fetching from Relaton repository ..."
184
194
  ref = full_ref
195
+ return [] if ref.empty?
196
+
185
197
  # fn = ref.gsub(%r{[/\s:.]}, "_").upcase
186
198
  index = Relaton::Index.find_or_create :nist, url: "#{GHNISTDATA}index-v1.zip", file: INDEX_FILE
187
199
  rows = index.search(ref).sort_by { |r| r[:id] }
@@ -209,20 +221,20 @@ module RelatonNist
209
221
  #
210
222
  # @return [Array<RelatonNist::Hit>] hits
211
223
  #
212
- def from_json
224
+ def from_json # rubocop:disable Metrics/AbcSize
225
+ Util.warn "(#{@reference}) Fetching from csrc.nist.gov ..."
213
226
  select_data.map do |h|
214
227
  /(?<series>(?<=-)\w+$)/ =~ h["series"]
215
228
  title = [h["title-main"], h["title-sub"]].compact.join " - "
216
229
  release_date = RelatonBib.parse_date h["published-date"], false
217
- Hit.new({ code: docidentifier(h), series: series.upcase, title: title,
218
- url: h["uri"], status: h["status"],
219
- release_date: release_date, json: h }, self)
230
+ Hit.new({ code: docidentifier(h), series: series.upcase, title: title, url: h["uri"],
231
+ status: h["status"], release_date: release_date, json: h }, self)
220
232
  end
221
233
  end
222
234
 
223
235
  def docidentifier(json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
224
- parts = doi_parts json
225
- return json["docidentifier"] unless parts
236
+ parts = doi_parts(json) || code_parts(json["docidentifier"])
237
+ # return json["docidentifier"] unless parts
226
238
 
227
239
  id = parts[:code]
228
240
  id = "NIST #{parts[:series]} #{id}" if parts[:series]
@@ -84,10 +84,10 @@ module RelatonNist
84
84
  result = nistbib_search_filter(code, year, opts) || (return nil)
85
85
  ret = nistbib_results_filter(result, year, opts)
86
86
  if ret[:ret]
87
- Util.warn "(#{code}) found `#{ret[:ret].docidentifier.first.id}`"
87
+ Util.warn "(#{result.reference}) Found: `#{ret[:ret].docidentifier.first.id}`"
88
88
  ret[:ret]
89
89
  else
90
- fetch_ref_err(code, year, ret[:years])
90
+ fetch_ref_err(result.reference, year, ret[:years])
91
91
  end
92
92
  end
93
93
 
@@ -114,20 +114,19 @@ module RelatonNist
114
114
  when "F" then "final"
115
115
  else iter
116
116
  end
117
- result.each_slice(3) do |s| # ISO website only allows 3 connections
118
- fetch_pages(s, 3).each_with_index do |r, _i|
119
- if opts[:date]
120
- dates = r.date.select { |d| d.on(:date) == opts[:date] }
121
- next if dates.empty?
122
- end
123
- next if iter && r.status.iteration != iteration
124
- return { ret: r } if !year
117
+ result.each do |h|
118
+ r = h.fetch
119
+ if opts[:date]
120
+ dates = r.date.select { |d| d.on(:date) == opts[:date] }
121
+ next if dates.empty?
122
+ end
123
+ next if iter && r.status.iteration != iteration
124
+ return { ret: r } if !year
125
125
 
126
- r.date.select { |d| d.type == "published" }.each do |d|
127
- return { ret: r } if year.to_i == d.on(:year)
126
+ r.date.select { |d| d.type == "published" }.each do |d|
127
+ return { ret: r } if year.to_i == d.on(:year)
128
128
 
129
- missed_years << d.on(:year)
130
- end
129
+ missed_years << d.on(:year)
131
130
  end
132
131
  end
133
132
  { years: missed_years }
@@ -141,13 +140,13 @@ module RelatonNist
141
140
  #
142
141
  # @return [Array<RelatonNist::NistBibliographicItem>] bibliographic items
143
142
  #
144
- def fetch_pages(hits, threads)
145
- workers = RelatonBib::WorkersPool.new threads
146
- workers.worker { |w| { i: w[:i], hit: w[:hit].fetch } }
147
- hits.each_with_index { |hit, i| workers << { i: i, hit: hit } }
148
- workers.end
149
- workers.result.sort_by { |a| a[:i] }.map { |x| x[:hit] }
150
- end
143
+ # def fetch_pages(hits, threads)
144
+ # workers = RelatonBib::WorkersPool.new threads
145
+ # workers.worker { |w| { i: w[:i], hit: w[:hit].fetch } }
146
+ # hits.each_with_index { |hit, i| workers << { i: i, hit: hit } }
147
+ # workers.end
148
+ # workers.result.sort_by { |a| a[:i] }.map { |x| x[:hit] }
149
+ # end
151
150
 
152
151
  #
153
152
  # Get search results and filter them by code and year
@@ -160,7 +159,6 @@ module RelatonNist
160
159
  # @return [RelatonNist::HitCollection] hits collection
161
160
  #
162
161
  def nistbib_search_filter(code, year, opts)
163
- Util.warn "(#{code}) fetching..."
164
162
  result = search(code, year, opts)
165
163
  result.search_filter
166
164
  end
@@ -168,21 +166,19 @@ module RelatonNist
168
166
  #
169
167
  # Outputs warning message if no match found
170
168
  #
171
- # @param [String] code reference
169
+ # @param [String] ref reference
172
170
  # @param [String, nil] year year
173
171
  # @param [Array<String>] missed_years missed years
174
172
  #
175
173
  # @return [nil] nil
176
174
  #
177
- def fetch_ref_err(code, year, missed_years) # rubocop:disable Metrics/MethodLength
178
- id = year ? "#{code}:#{year}" : code
179
- Util.warn "WARNING: no match found online for `#{id}`. " \
180
- "The code must be exactly like it is on the standards website."
175
+ def fetch_ref_err(ref, year, missed_years)
176
+ Util.warn "(#{ref}) No found."
181
177
  unless missed_years.empty?
182
178
  Util.warn "(There was no match for #{year}, though there " \
183
179
  "were matches found for `#{missed_years.join('`, `')}`.)"
184
180
  end
185
- if /\d-\d/.match? code
181
+ if /\d-\d/.match? ref
186
182
  Util.warn "The provided document part may not exist, " \
187
183
  "or the document may no longer be published in parts."
188
184
  end
@@ -51,7 +51,7 @@ module RelatonNist
51
51
  script: [json["script"]],
52
52
  docstatus: fetch_status(json), # hit_data[:status]),
53
53
  copyright: fetch_copyright(json["published-date"]),
54
- relation: fetch_relations_json(json),
54
+ relation: fetch_relations_json(hit_data),
55
55
  place: ["Gaithersburg, MD"],
56
56
  keyword: fetch_keywords(json),
57
57
  commentperiod: fetch_commentperiod_json(json),
@@ -80,10 +80,18 @@ module RelatonNist
80
80
  def fetch_status(doc)
81
81
  stage = doc["status"]
82
82
  subst = doc["substage"]
83
- iter = doc["iteration"] == "initial" ? 1 : doc["iteration"]
83
+ iter = iteration(doc["iteration"])
84
84
  RelatonNist::DocumentStatus.new stage: stage, substage: subst, iteration: iter.to_s
85
85
  end
86
86
 
87
+ def iteration(iter)
88
+ case iter
89
+ when "initial", "ipd" then 1
90
+ when /(\d)pd/i then $1
91
+ else iter
92
+ end
93
+ end
94
+
87
95
  # Fetch titles.
88
96
  # @param hit_data [Hash]
89
97
  # @return [Array<Hash>]
@@ -109,7 +117,7 @@ module RelatonNist
109
117
  # d = doc.at("//span[@id='pub-release-date']")&.text&.strip
110
118
  # issued = RelatonBib.parse_date d
111
119
  # end
112
- dates << { type: "issued", on: issued.to_s }
120
+ dates << { type: "issued", on: issued.to_s } if issued
113
121
  dates
114
122
  end
115
123
 
@@ -182,9 +190,9 @@ module RelatonNist
182
190
  # @return [String, NilClass]
183
191
  def fetch_edition(doc)
184
192
  # if doc.is_a? Hash
185
- return unless doc["edition"]
193
+ return unless doc["edition"] || doc["revision"]
186
194
 
187
- rev = doc["edition"]
195
+ rev = doc["edition"] || doc["revision"]
188
196
  "Revision #{rev}"
189
197
  end
190
198
 
@@ -210,13 +218,14 @@ module RelatonNist
210
218
  links
211
219
  end
212
220
 
213
- def fetch_relations_json(doc)
221
+ def fetch_relations_json(hit)
222
+ doc = hit[:json]
214
223
  relations = doc["supersedes"].map do |r|
215
- doc_relation "supersedes", r["docidentifier"], r["uri"]
224
+ doc_relation "supersedes", hit[:code], r["uri"]
216
225
  end
217
226
 
218
227
  relations + doc["superseded-by"].map do |r|
219
- doc_relation "updates", r["docidentifier"], r["uri"]
228
+ doc_relation "updates", hit[:code], r["uri"]
220
229
  end
221
230
  end
222
231
 
@@ -230,16 +239,11 @@ module RelatonNist
230
239
  t = "obsoletes"
231
240
  else t = type
232
241
  end
233
- DocumentRelation.new(
234
- type: t,
235
- description: descr,
236
- bibitem: RelatonBib::BibliographicItem.new(
237
- formattedref: RelatonBib::FormattedRef.new(
238
- content: ref, language: lang, script: script, format: "text/plain",
239
- ),
240
- link: [RelatonBib::TypedUri.new(type: "src", content: uri)],
241
- ),
242
- )
242
+ ids = [RelatonBib::DocumentIdentifier.new(id: ref, type: "NIST", primary: true)]
243
+ fref = RelatonBib::FormattedRef.new(content: ref, language: lang, script: script, format: "text/plain")
244
+ link = [RelatonBib::TypedUri.new(type: "src", content: uri)]
245
+ bib = RelatonBib::BibliographicItem.new(formattedref: fref, link: link, docid: ids)
246
+ DocumentRelation.new(type: t, description: descr, bibitem: bib)
243
247
  end
244
248
 
245
249
  # @param doc [Hash]
@@ -1,3 +1,3 @@
1
1
  module RelatonNist
2
- VERSION = "1.16.3".freeze
2
+ VERSION = "1.16.4".freeze
3
3
  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.16.3
4
+ version: 1.16.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-04 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: relaton-bib