nistbib 0.1.5 → 0.1.6

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
  SHA1:
3
- metadata.gz: 93e42e10363b0cf5ace10ea2540e20a7d96bacfa
4
- data.tar.gz: 958b66ae4601efb35dbd366a80b5c09ea22a50bd
3
+ metadata.gz: 896a6c8fd4132200e685aa768a3bab6f089f9f4b
4
+ data.tar.gz: f399bbd50fcbe7cb1f70d4dee3fb37619f5b051a
5
5
  SHA512:
6
- metadata.gz: 4fb26a328169066da7e921df16b525a67baa6fc5b8ddebb14fbcb08af41decddd6e27b40a173aa9015972e9a22f844ceea4ee7dd711444600efac36a240a49eb
7
- data.tar.gz: e71f295627f4f640f81432508783365ccbc868cc98f277ecb153e920a9e62339d6cf79f81f64d8ee731b09ede32414d3322a9ab162dce416b543fc040da0055b
6
+ metadata.gz: 28bde9d7d3a30d628a53e0f06a4444859b870aea0a65fcab7ca9315e2330f0a86017b1bce5ea74636ea6b8480e26b294816319f338c1a2081cdaceb0d56b833a
7
+ data.tar.gz: 5ba05e4c1ecb61b89a05a67c042ec4ce32119f23a139aca620c2715c1177d1eb75c4482a433e2dc5913d910f53c12483fad737b4b1c4b3e8aeea694dfa367fb2
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nistbib (0.1.5)
5
- relaton-bib (~> 0.1.1)
4
+ nistbib (0.1.6)
5
+ relaton-bib (~> 0.1.5)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -34,7 +34,7 @@ GEM
34
34
  pry (~> 0.10)
35
35
  public_suffix (3.0.3)
36
36
  rake (10.5.0)
37
- relaton-bib (0.1.3)
37
+ relaton-bib (0.1.5)
38
38
  addressable
39
39
  nokogiri (~> 1.8.4)
40
40
  rspec (3.8.0)
data/README.adoc CHANGED
@@ -48,13 +48,35 @@ hit_collection = NistBib::NistBibliography.search("8200")
48
48
  [source,ruby]
49
49
  ----
50
50
  item.to_xml
51
- => "<nist-standard>
51
+ => "<bibitem id="NISTIR8200(DRAFT)" type="standard">
52
52
  <fetched>2019-05-03</fetched>
53
53
  <title format="text/plain" language="en" script="Latn">
54
54
  Interagency Report on Status of International Cybersecurity Standardization for the Internet of Things (IoT)
55
55
  </title>
56
56
  ...
57
- </nist-standard>"
57
+ <bibitem>"
58
+ ----
59
+ With argument `bibdata: true` it ouputs XML wrapped by `bibdata` element and adds flavour `ext` element.
60
+ [source,ruby]
61
+ ----
62
+ item.to_xml bibdata: true
63
+ => "<bibdata type="standard">
64
+ <fetched>2019-05-17</fetched>
65
+ <title format="text/plain" language="en" script="Latn">
66
+ Interagency Report on Status of International Cybersecurity Standardization for the Internet of Things (IoT)
67
+ </title>
68
+ ...
69
+ <ext>
70
+ <doctype>stadard</doctype>
71
+ <keyword>cybersecurity</keyword>
72
+ <keyword>cybersecurity objectives</keyword>
73
+ ...
74
+ <commentperiod>
75
+ <from>2018-02-01</from>
76
+ <to>2018-04-18</to>
77
+ </commentperiod>
78
+ </ext>
79
+ </bibdata>"
58
80
  ----
59
81
 
60
82
  === Get code, and year
@@ -1,20 +1,11 @@
1
1
  module NistBib
2
- class DocumentStatus
2
+ class DocumentStatus < RelatonBib::DocumentStatus
3
3
  STAGES = %w[
4
4
  draft-internal draft-wip draft-prelim draft-public final final-review
5
5
  ].freeze
6
6
 
7
7
  SUBSTAGES = %w[active retired withdrawn].freeze
8
8
 
9
- # @return [String]
10
- attr_reader :stage
11
-
12
- # @return [String, NilClass]
13
- attr_reader :substage
14
-
15
- # @return [String, NilClass]
16
- attr_reader :iteration
17
-
18
9
  # @param stage [String]
19
10
  # @param substage [String, NilClass]
20
11
  # @param iteration [String, NilClass]
@@ -27,18 +18,7 @@ module NistBib
27
18
  raise ArgumentError, "invalid argument: substage (#{substage})"
28
19
  end
29
20
 
30
- @stage = stage
31
- @substage = substage
32
- @iteration = iteration
33
- end
34
-
35
- # @param builder [Nokogiri::XML::Builder]
36
- def to_xml(builder)
37
- builder.status do
38
- builder.stage stage
39
- builder.substage substage if substage
40
- builder.iteration iteration if iteration
41
- end
21
+ super
42
22
  end
43
23
  end
44
24
  end
data/lib/nistbib/hit.rb CHANGED
@@ -37,8 +37,8 @@ module NistBib
37
37
  end
38
38
 
39
39
  # @return [String]
40
- def to_xml
41
- fetch.to_xml
40
+ def to_xml(**opts)
41
+ fetch.to_xml **opts
42
42
  end
43
43
  end
44
44
  end
@@ -23,6 +23,7 @@ module NistBib
23
23
  # @param ref_nbr [String]
24
24
  # @param year [String]
25
25
  # @param opts [Hash]
26
+ # @option opts [String] :stage
26
27
  def initialize(ref_nbr, year = nil, opts)
27
28
  @text = ref_nbr
28
29
  @year = year
@@ -35,7 +36,7 @@ module NistBib
35
36
  url = "#{DOMAIN}/publications/search?keywords-lg=#{ref_nbr}"
36
37
  url += "&dateFrom-lg=#{from}" if from
37
38
  url += "&dateTo-lg=#{to}" if to
38
- url += "&status-lg=Draft" if /PD/ =~ opts[:stage]
39
+ url += "&status-lg=Draft,Withdrawn" if /PD/ =~ opts[:stage]
39
40
  doc = Nokogiri::HTML OpenURI.open_uri(::Addressable::URI.parse(url).normalize)
40
41
  hits = doc.css("table.publications-table > tbody > tr").map do |h|
41
42
  link = h.at("td/div/strong/a")
@@ -1,7 +1,7 @@
1
1
  module NistBib
2
2
  class NistBibliographicItem < RelatonBib::BibliographicItem
3
- # @return [NistBib::NistSeries, NilClass]
4
- attr_reader :nistseries
3
+ # @return [String]
4
+ attr_reader :doctype
5
5
 
6
6
  # @return [Array<NistBib::Keyword>]
7
7
  attr_reader :keyword
@@ -29,6 +29,7 @@ module NistBib
29
29
  # @param classification [RelatonBib::Classification, NilClass]
30
30
  # @param validity [RelatonBib:Validity, NilClass]
31
31
  # @param fetched [Date, NilClass] default nil
32
+ # @param doctype [String]
32
33
  # @param keyword [Array<NistBib::Keyword>]
33
34
  # @param commentperiod [NistBib::CommentPeriod]
34
35
  #
@@ -54,21 +55,23 @@ module NistBib
54
55
  # @option relations [String] :type
55
56
  # @option relations [RelatonBib::BibliographicItem] :bibitem
56
57
  # @option relations [Array<RelatonBib::BibItemLocality>] :bib_locality
57
- #
58
- # @param nistseries [Nist::NistSeries, NilClass]
59
58
  def initialize(**args)
60
- @nistseries = args.delete :nistseries
59
+ @doctype = "stadard"
61
60
  @keyword = args.delete(:keyword) || []
62
61
  @commentperiod = args.delete :commentperiod
63
62
  super
64
63
  end
65
64
 
66
65
  # @param builder [Nokogiri::XML::Builder]
67
- def to_xml(builder = nil)
68
- super builder, root: :bibitem, date_format: :short do |b|
69
- nistseries&.to_xml b
70
- keyword.each { |kw| kw.to_xml b }
71
- commentperiod&.to_xml b
66
+ def to_xml(builder = nil, **opts)
67
+ super builder, date_format: :short, **opts do |b|
68
+ if opts[:bibdata]
69
+ b.ext do
70
+ b.doctype doctype
71
+ keyword.each { |kw| kw.to_xml b }
72
+ commentperiod&.to_xml b
73
+ end
74
+ end
72
75
  end
73
76
  end
74
77
  end
@@ -2,7 +2,6 @@ require "relaton_bib"
2
2
  require "nistbib/nist_bibliographic_item"
3
3
  require "nistbib/scrapper"
4
4
  require "nistbib/hit_collection"
5
- require "nistbib/nist_series"
6
5
  require "nistbib/xml_parser"
7
6
  require "nistbib/keyword"
8
7
  require "nistbib/comment_period"
@@ -22,10 +21,15 @@ module NistBib
22
21
 
23
22
  # @param code [String] the NIST standard Code to look up (e..g "8200")
24
23
  # @param year [String] the year the standard was published (optional)
25
- # @param opts [Hash] options; restricted to :all_parts if all-parts reference is required
24
+ #
25
+ # @param opts [Hash] options
26
+ # @option opts [TrueClass, FalseClass] :all_parts restricted to all parts
27
+ # if all-parts reference is required
28
+ # @option opts [TrueClass, FalseClass] :bibdata
29
+ #
26
30
  # @return [String] Relaton XML serialisation of reference
27
31
  def get(code, year = nil, opts = {})
28
- /^(?<code2>[^\(]+)\((?<date2>\w+\s(\d{2},\s)?\d{4})\)(\s\()?(?<stage>[^\)]+)?/ =~ code
32
+ /^(?<code2>[^\(]+)(\((?<date2>\w+\s(\d{2},\s)?\d{4})\))?\s?\(?((?<=\()(?<stage>[^\)]+))?/ =~ code
29
33
  if code2
30
34
  code = code2.strip
31
35
  if date2
@@ -57,7 +61,7 @@ module NistBib
57
61
  private
58
62
 
59
63
  def nistbib_get1(code, year, opts)
60
- result = nistbib_search_filter(code, year, opts) or return nil
64
+ result = nistbib_search_filter(code, year, opts) || (return nil)
61
65
  ret = nistbib_results_filter(result, year, opts)
62
66
  return ret[:ret] if ret[:ret]
63
67
 
@@ -70,19 +74,35 @@ module NistBib
70
74
  # Only expects the first page of results to be populated.
71
75
  # Does not match corrigenda etc (e.g. ISO 3166-1:2006/Cor 1:2007)
72
76
  # If no match, returns any years which caused mismatch, for error reporting
77
+ #
78
+ # @param opts [Hash] options
79
+ # @option opts [Time] :issued_date
80
+ # @option opts [Time] :issued_date
81
+ # @option opts [String] :stage
82
+ #
83
+ # @retur [Hash]
73
84
  def nistbib_results_filter(result, year, opts)
74
85
  missed_years = []
75
86
  result.each_slice(3) do |s| # ISO website only allows 3 connections
76
87
  fetch_pages(s, 3).each_with_index do |r, _i|
77
88
  if opts[:issued_date]
78
89
  r.dates.select { |d| d.type == "issued" }.each do |d|
79
- return { ret: r } if opts[:issued_date] == d.on
90
+ next unless opts[:issued_date] == d.on
80
91
  end
81
92
  elsif opts[:updated_date]
82
93
  r.dates.select { |d| d.type == "published" }.each do |d|
83
- return { ret: r } if opts[:updated_date] == d.on
94
+ next unless opts[:updated_date] == d.on
84
95
  end
85
96
  end
97
+ if opts[:stage]
98
+ iter = opts[:stage][-3]
99
+ iteration = case iter
100
+ when "I" then 1
101
+ when "F" then "final"
102
+ else iter.to_i
103
+ end
104
+ next if iter && r.status.iteration != iteration
105
+ end
86
106
  return { ret: r } if !year
87
107
 
88
108
  r.dates.select { |d| d.type == "published" }.each do |d|
@@ -15,20 +15,20 @@ module NistBib
15
15
  NistBibliographicItem.new(
16
16
  fetched: Date.today.to_s,
17
17
  type: "standard",
18
- id: fetch_id(doc),
18
+ # id: fetch_id(doc),
19
19
  titles: fetch_titles(hit_data),
20
20
  link: fetch_link(doc),
21
21
  docid: fetch_docid(doc),
22
22
  dates: fetch_dates(doc, hit_data[:release_date]),
23
23
  contributors: fetch_contributors(doc),
24
- edition: nil,
24
+ edition: fetch_edition(hit_data[:code]),
25
25
  language: ["en"],
26
26
  script: ["Latn"],
27
27
  abstract: fetch_abstract(doc),
28
28
  docstatus: fetch_status(doc, hit_data[:status]),
29
29
  copyright: fetch_copyright(doc),
30
30
  relations: fetch_relations(doc),
31
- nistseries: fetch_nistseries(doc),
31
+ series: fetch_series(doc),
32
32
  keyword: fetch_keywords(doc),
33
33
  commentperiod: fetch_commentperiod(doc),
34
34
  )
@@ -47,7 +47,7 @@ module NistBib
47
47
 
48
48
  # Fetch docid.
49
49
  # @param doc [Nokogiri::HTML::Document]
50
- # @return [Hash]
50
+ # @return [Array<RelatonBib::DocumentIdentifier>]
51
51
  def fetch_docid(doc)
52
52
  item_ref = doc.at("//div[contains(@class, 'publications-detail')]/h3").
53
53
  text.strip
@@ -59,10 +59,10 @@ module NistBib
59
59
  # Fetch id.
60
60
  # @param doc [Nokogiri::HTML::Document]
61
61
  # @return [String]
62
- def fetch_id(doc)
63
- doc.at("//div[contains(@class, 'publications-detail')]/h3").text.
64
- strip.gsub(/\s/, "")
65
- end
62
+ # def fetch_id(doc)
63
+ # doc.at("//div[contains(@class, 'publications-detail')]/h3").text.
64
+ # strip.gsub(/\s/, "")
65
+ # end
66
66
 
67
67
  # Fetch status.
68
68
  # @param doc [Nokogiri::HTML::Document]
@@ -72,19 +72,36 @@ module NistBib
72
72
  case status
73
73
  when "draft (withdrawn)"
74
74
  stage = "draft-public"
75
- substage = "withdrawn"
75
+ subst = "withdrawn"
76
76
  when "retired draft"
77
77
  stage = "draft-public"
78
- substage = "retired"
78
+ subst = "retired"
79
79
  when "withdrawn"
80
80
  stage = "final"
81
- substage = "withdrawn"
81
+ subst = "withdrawn"
82
82
  when "draft"
83
83
  stage = "draft-public"
84
- substage = "active"
84
+ subst = "active"
85
85
  else
86
86
  stage = status
87
- substage = "active"
87
+ subst = "active"
88
+ end
89
+
90
+ iter = nil
91
+ if stage.include? "draft"
92
+ iter = 1
93
+ history = doc.xpath("//span[@id='pub-history-container']/a"\
94
+ "|//span[@id='pub-history-container']/span")
95
+ history.each_with_index do |h, idx|
96
+ next if h.name == "a"
97
+
98
+ iter = idx + 1 if idx.positive?
99
+ # iter = if lsif idx < (history.size - 1) && !history.last.text.include?("Draft")
100
+ # "final"
101
+ # elsif idx.positive? then idx + 1
102
+ # end
103
+ break
104
+ end
88
105
  end
89
106
 
90
107
  # if doc.at "//p/strong[text()='Withdrawn:']"
@@ -97,7 +114,7 @@ module NistBib
97
114
  # wip = item_ref.match(/(?<=\()\w+/).to_s
98
115
  # stage = "draft-public" if wip == "DRAFT"
99
116
  # end
100
- NistBib::DocumentStatus.new(stage: stage, substage: substage)
117
+ NistBib::DocumentStatus.new stage: stage, substage: subst, iteration: iter
101
118
  end
102
119
 
103
120
  # Fetch titles.
@@ -140,6 +157,7 @@ module NistBib
140
157
  contribs + contributors(editors, "editor")
141
158
  end
142
159
 
160
+ # rubocop:disable Metrics/CyclomaticComplexity
143
161
  def contributors(doc, role)
144
162
  return [] if doc.nil?
145
163
 
@@ -171,6 +189,13 @@ module NistBib
171
189
  RelatonBib::ContributionInfo.new entity: entity, role: [role]
172
190
  end
173
191
  end
192
+ # rubocop:enable Metrics/CyclomaticComplexity
193
+
194
+ def fetch_edition(code)
195
+ return unless /(?<=Rev\.\s)(?<rev>\d+)/ =~ code
196
+
197
+ "Revision #{rev}"
198
+ end
174
199
 
175
200
  # Fetch abstracts.
176
201
  # @param doc [Nokigiri::HTML::Document]
@@ -238,13 +263,28 @@ module NistBib
238
263
  )
239
264
  end
240
265
 
241
- def fetch_nistseries(doc)
242
- doc.xpath("//p/strong[.='Document History:']/following-sibling::*[not(self::br)]").each do |s|
243
- NistSeries::ABBREVIATIONS.each do |k, _v|
244
- return NistSeries.new k if s.text.include? k
245
- end
246
- end
247
- nil
266
+ def fetch_series(doc)
267
+ series = doc.xpath "//span[@id='pub-history-container']/a"\
268
+ "|//span[@id='pub-history-container']/span"
269
+ series.map.with_index do |s, idx|
270
+ next if s.name == "span"
271
+
272
+ iter = if idx.zero? then "I"
273
+ # elsif status == "final" && idx == (series.size - 1) then "F"
274
+ else idx + 1
275
+ end
276
+
277
+ content = s.text.match(/^[^\(]+/).to_s.strip.gsub " ", " "
278
+
279
+ ref = case content.match(/\w+/).to_s
280
+ when "Draft" then content.match(/(?<=Draft\s).+/).to_s + " (#{iter}PD)"
281
+ end
282
+
283
+ fref = RelatonBib::FormattedRef.new(
284
+ content: ref, language: "en", script: "Latn", format: "text/plain",
285
+ )
286
+ RelatonBib::Series.new(formattedref: fref)
287
+ end.select { |s| s }
248
288
  end
249
289
 
250
290
  def fetch_keywords(doc)
@@ -1,3 +1,3 @@
1
1
  module NistBib
2
- VERSION = "0.1.5".freeze
2
+ VERSION = "0.1.6".freeze
3
3
  end
@@ -3,7 +3,7 @@ module NistBib
3
3
  class << self
4
4
  def from_xml(xml)
5
5
  doc = Nokogiri::XML xml
6
- nistitem = doc.at("/bibitem") || doc.at("/bibdata")
6
+ nistitem = doc.at("/bibitem|/bibdata")
7
7
  NistBibliographicItem.new(item_data(nistitem))
8
8
  end
9
9
 
@@ -11,10 +11,11 @@ module NistBib
11
11
 
12
12
  def item_data(nistitem)
13
13
  data = super
14
- data.delete :series
15
- data[:nistseries] = fetch_nistseries(nistitem)
16
- data[:keyword] = fetch_keyword(nistitem)
17
- data[:commentperiod] = fetch_commentperiod(nistitem)
14
+ ext = nistitem.at "./ext"
15
+ return data unless ext
16
+
17
+ data[:keyword] = fetch_keyword(ext)
18
+ data[:commentperiod] = fetch_commentperiod(ext)
18
19
  data
19
20
  end
20
21
 
@@ -25,7 +26,7 @@ module NistBib
25
26
  DocumentStatus.new(
26
27
  stage: status.at("stage")&.text,
27
28
  substage: status.at("substage")&.text,
28
- iteration: status.at("iteraton")&.text,
29
+ iteration: status.at("iteration")&.text,
29
30
  )
30
31
  end
31
32
 
@@ -41,13 +42,6 @@ module NistBib
41
42
  Keyword.new kw.children.first.to_xml
42
43
  end
43
44
  end
44
-
45
- def fetch_nistseries(item)
46
- series = item.at "./series"
47
- return unless series
48
-
49
- NistSeries.new series.at("./abbreviation").text.upcase.gsub("-", " ")
50
- end
51
45
  end
52
46
  end
53
47
  end
@@ -11,7 +11,7 @@ module Relaton
11
11
  @idtype = "NIST"
12
12
  end
13
13
 
14
- def get(code, date, opts)
14
+ def get(code, date = nil, opts = {})
15
15
  ::NistBib::NistBibliography.get(code, date, opts)
16
16
  end
17
17
 
data/nistbib.gemspec CHANGED
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "vcr"
35
35
  spec.add_development_dependency "webmock"
36
36
 
37
- spec.add_dependency "relaton-bib", "~> 0.1.1"
37
+ spec.add_dependency "relaton-bib", "~> 0.1.5"
38
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nistbib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-13 00:00:00.000000000 Z
11
+ date: 2019-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.1.1
173
+ version: 0.1.5
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.1.1
180
+ version: 0.1.5
181
181
  description: 'NistBib: retrive NIST standards.'
182
182
  email:
183
183
  - open.source@ribose.com
@@ -205,7 +205,6 @@ files:
205
205
  - lib/nistbib/keyword.rb
206
206
  - lib/nistbib/nist_bibliographic_item.rb
207
207
  - lib/nistbib/nist_bibliography.rb
208
- - lib/nistbib/nist_series.rb
209
208
  - lib/nistbib/scrapper.rb
210
209
  - lib/nistbib/version.rb
211
210
  - lib/nistbib/workers_pool.rb
@@ -1,35 +0,0 @@
1
- module NistBib
2
- class NistSeries
3
- ABBREVIATIONS = {
4
- "NISTIR" => "NIST Interagency/Internal Report",
5
- "NIST SP" => "NIST Special Publication",
6
- "NIST FIPS" => "NIST Federal Information Processing Standards",
7
- }.freeze
8
-
9
- # @return [String]
10
- attr_reader :type
11
-
12
- # @return [String]
13
- attr_reader :title
14
-
15
- # @return [RalatonBib::LocalizedString, NilClass]
16
- attr_reader :abbreviation
17
-
18
- # @param abbreviation [RelatonBib::LocalizedString, NilClass]
19
- def initialize(abbreviation)
20
- @type = "main"
21
- @abbreviation = RelatonBib::LocalizedString.new(
22
- abbreviation.downcase.gsub(" ", "-"), "en", "Latn"
23
- )
24
- @title = ABBREVIATIONS[abbreviation]
25
- end
26
-
27
- # @param builder [Nokogiri::XML::Builder]
28
- def to_xml(builder)
29
- builder.series type: type do
30
- builder.title title
31
- builder.abbreviation { abbreviation.to_xml builder } if abbreviation
32
- end
33
- end
34
- end
35
- end