relaton-ieee 1.1.0

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.
@@ -0,0 +1,165 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
3
+ <!--
4
+ Presupposes isodoc.rnc, is included in it
5
+ include "isodoc.rnc" { }
6
+ -->
7
+ <define name="requirement">
8
+ <element name="requirement">
9
+ <ref name="RequirementType"/>
10
+ </element>
11
+ </define>
12
+ <define name="recommendation">
13
+ <element name="recommendation">
14
+ <ref name="RequirementType"/>
15
+ </element>
16
+ </define>
17
+ <define name="permission">
18
+ <element name="permission">
19
+ <ref name="RequirementType"/>
20
+ </element>
21
+ </define>
22
+ <define name="RequirementType">
23
+ <optional>
24
+ <attribute name="obligation">
25
+ <ref name="ObligationType"/>
26
+ </attribute>
27
+ </optional>
28
+ <optional>
29
+ <attribute name="unnumbered">
30
+ <data type="boolean"/>
31
+ </attribute>
32
+ </optional>
33
+ <optional>
34
+ <attribute name="subsequence"/>
35
+ </optional>
36
+ <attribute name="id">
37
+ <data type="ID"/>
38
+ </attribute>
39
+ <optional>
40
+ <attribute name="filename"/>
41
+ </optional>
42
+ <optional>
43
+ <ref name="reqtitle"/>
44
+ </optional>
45
+ <optional>
46
+ <ref name="label"/>
47
+ </optional>
48
+ <optional>
49
+ <ref name="subject"/>
50
+ </optional>
51
+ <optional>
52
+ <ref name="reqinherit"/>
53
+ </optional>
54
+ <zeroOrMore>
55
+ <ref name="classification"/>
56
+ </zeroOrMore>
57
+ <zeroOrMore>
58
+ <choice>
59
+ <ref name="measurementtarget"/>
60
+ <ref name="specification"/>
61
+ <ref name="verification"/>
62
+ <ref name="import"/>
63
+ <ref name="description"/>
64
+ </choice>
65
+ </zeroOrMore>
66
+ <optional>
67
+ <ref name="reqt_references"/>
68
+ </optional>
69
+ <zeroOrMore>
70
+ <choice>
71
+ <ref name="requirement"/>
72
+ <ref name="recommendation"/>
73
+ <ref name="permission"/>
74
+ </choice>
75
+ </zeroOrMore>
76
+ </define>
77
+ <define name="reqtitle">
78
+ <element name="title">
79
+ <ref name="FormattedString"/>
80
+ </element>
81
+ </define>
82
+ <define name="label">
83
+ <element name="label">
84
+ <text/>
85
+ </element>
86
+ </define>
87
+ <define name="subject">
88
+ <element name="subject">
89
+ <text/>
90
+ </element>
91
+ </define>
92
+ <define name="reqinherit">
93
+ <element name="inherit">
94
+ <text/>
95
+ </element>
96
+ </define>
97
+ <define name="measurementtarget">
98
+ <element name="measurement-target">
99
+ <ref name="RequirementSubpart"/>
100
+ </element>
101
+ </define>
102
+ <define name="specification">
103
+ <element name="specification">
104
+ <ref name="RequirementSubpart"/>
105
+ </element>
106
+ </define>
107
+ <define name="verification">
108
+ <element name="verification">
109
+ <ref name="RequirementSubpart"/>
110
+ </element>
111
+ </define>
112
+ <define name="import">
113
+ <element name="import">
114
+ <ref name="RequirementSubpart"/>
115
+ </element>
116
+ </define>
117
+ <define name="description">
118
+ <element name="description">
119
+ <ref name="RequirementSubpart"/>
120
+ </element>
121
+ </define>
122
+ <define name="reqt_references">
123
+ <element name="references">
124
+ <oneOrMore>
125
+ <ref name="bibitem"/>
126
+ </oneOrMore>
127
+ </element>
128
+ </define>
129
+ <define name="RequirementSubpart">
130
+ <optional>
131
+ <attribute name="type"/>
132
+ </optional>
133
+ <optional>
134
+ <attribute name="exclude">
135
+ <data type="boolean"/>
136
+ </attribute>
137
+ </optional>
138
+ <oneOrMore>
139
+ <ref name="BasicBlock"/>
140
+ </oneOrMore>
141
+ </define>
142
+ <define name="ObligationType">
143
+ <choice>
144
+ <value>requirement</value>
145
+ <value>recommendation</value>
146
+ <value>permission</value>
147
+ </choice>
148
+ </define>
149
+ <define name="classification">
150
+ <element name="classification">
151
+ <ref name="classification_tag"/>
152
+ <ref name="classification_value"/>
153
+ </element>
154
+ </define>
155
+ <define name="classification_tag">
156
+ <element name="tag">
157
+ <text/>
158
+ </element>
159
+ </define>
160
+ <define name="classification_value">
161
+ <element name="value">
162
+ <text/>
163
+ </element>
164
+ </define>
165
+ </grammar>
@@ -0,0 +1,25 @@
1
+ require "digest/md5"
2
+ require "yaml"
3
+ require "relaton_bib"
4
+ require "relaton_ieee/version"
5
+ require "relaton_ieee/ieee_bibliography"
6
+ require "relaton_ieee/hit_collection"
7
+ require "relaton_ieee/hit"
8
+ require "relaton_ieee/scrapper"
9
+ require "relaton_ieee/ieee_bibliographic_item"
10
+ require "relaton_ieee/committee"
11
+ require "relaton_ieee/xml_parser"
12
+ require "relaton_ieee/hash_converter"
13
+
14
+ module RelatonIeee
15
+ class Error < StandardError; end
16
+
17
+ # Returns hash of XML reammar
18
+ # @return [String]
19
+ def self.grammar_hash
20
+ gem_path = File.expand_path "..", __dir__
21
+ grammars_path = File.join gem_path, "grammars", "*"
22
+ grammars = Dir[grammars_path].sort.map { |gp| File.read gp }.join
23
+ Digest::MD5.hexdigest grammars
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ module RelatonIeee
2
+ class Committee
3
+ # @return [String]
4
+ attr_reader :type, :name
5
+
6
+ # @return [String, NilClass]
7
+ attr_reader :chair
8
+
9
+ # @param type [String]
10
+ # @param name [String]
11
+ # @param chair [String, NilClass]
12
+ def initialize(type:, name:, chair: nil)
13
+ @type = type
14
+ @name = name
15
+ @chair = chair
16
+ end
17
+
18
+ # @param builder [Nokogiri::XML::Builder]
19
+ def to_xml(builder)
20
+ builder.committee type: type do |b|
21
+ b.name name
22
+ b.chair chair if chair
23
+ end
24
+ end
25
+
26
+ # @return [Hash]
27
+ def to_hash
28
+ hash = { "type" => type, "name" => name }
29
+ hash["chair"] = chair if chair
30
+ hash
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module RelatonIeee
2
+ class HashConverter < RelatonBib::HashConverter
3
+ class << self
4
+ # @param args [Hash]
5
+ # @param neated [TrueClas, FalseClass] default true
6
+ # @return [Hash]
7
+ def hash_to_bib(args, nested = false)
8
+ hash = super
9
+ return nil unless hash.is_a?(Hash)
10
+
11
+ committee_hash_to_bib hash
12
+ hash
13
+ end
14
+
15
+ # @param item_hash [Hash]
16
+ # @return [RelatonIeee::IeeeBibliographicItem]
17
+ def bib_item(item_hash)
18
+ IeeeBibliographicItem.new item_hash
19
+ end
20
+
21
+ # @param hash [Hash]
22
+ def committee_hash_to_bib(hash)
23
+ return unless hash[:committee]
24
+
25
+ hash[:committee] = hash[:committee].map { |c| Committee.new c }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module RelatonIeee
2
+ class Hit < RelatonBib::Hit
3
+ # Parse page.
4
+ # @return [RelatonIeee::IeeeBliographicItem]
5
+ def fetch
6
+ @fetch ||= Scrapper.parse_page hit
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ require "faraday"
2
+ require "relaton_ieee/hit"
3
+ require "fileutils"
4
+
5
+ module RelatonIeee
6
+ class HitCollection < RelatonBib::HitCollection
7
+ DOMAIN = "https://standards.ieee.org".freeze
8
+ DATADIR = File.expand_path ".relaton/ogc/", Dir.home
9
+ DATAFILE = File.expand_path "bibliography.json", DATADIR
10
+ ETAGFILE = File.expand_path "etag.txt", DATADIR
11
+
12
+ # rubocop:disable Metrics/AbcSize
13
+
14
+ # @param ref [Strig]
15
+ # @param opts [Hash]
16
+ def initialize(ref)
17
+ super
18
+ code = ref.sub /^IEEE\s/, ""
19
+ search = CGI.escape({ data: { searchTerm: code } }.to_json)
20
+ url = "#{DOMAIN}/bin/standards/search?data=#{search}"
21
+ resp = Faraday.get url
22
+ resp_json = JSON.parse resp.body
23
+ json = JSON.parse resp_json["message"]
24
+ @array = json["response"]["searchResults"]["resultsMapList"].
25
+ reduce([]) do |s, hit|
26
+ /^(?<id>\d+)-(?<year>\d{4})/ =~ hit["record"]["recordTitle"]
27
+ next s unless id && code =~ %r{^#{id}}
28
+
29
+ s << Hit.new(hit["record"].merge(code: id, year: year.to_i), self)
30
+ end.sort_by { |h| h.hit[:year].to_s + h.hit["recordURL"] }.reverse
31
+ end
32
+ # rubocop:enable Metrics/AbcSize
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ module RelatonIeee
2
+ class IeeeBibliographicItem < RelatonBib::BibliographicItem
3
+ # @return [Array<RelatonIeee::Committee>]
4
+ attr_reader :committee
5
+
6
+ # @param committee [Array<RelatonIeee::Committee>]
7
+ def initialize(**args)
8
+ @committee = args.delete :committee
9
+ super
10
+ end
11
+
12
+ # @param builder [Nokogiri::XML::Bilder]
13
+ # @parma bibdata [TrueClass, FalseClass, NilClass]
14
+ def to_xml(builder = nil, **opts)
15
+ super do |bldr|
16
+ if opts[:bibdata] && committee.any?
17
+ bldr.ext do |b|
18
+ committee.each { |c| c.to_xml b }
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # @return [Hash]
25
+ def to_hash
26
+ hash = super
27
+ hash["committee"] = committee.map &:to_hash
28
+ hash
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,72 @@
1
+ module RelatonIeee
2
+ class IeeeBibliography
3
+ class << self
4
+ # @param text [String]
5
+ # @return [RelatonIeee::HitCollection]
6
+ def search(text)
7
+ HitCollection.new text
8
+ rescue Faraday::ConnectionFailed
9
+ raise RelatonBib::RequestError, "Could not access #{HitCollection::DOMAIN}"
10
+ end
11
+
12
+ # @param code [String] the IEEE standard Code to look up (e..g "528-2019")
13
+ # @param year [String] the year the standard was published (optional)
14
+ # @param opts [Hash] options
15
+ #
16
+ # @return [Hash, NilClass] returns { ret: RelatonBib::BibliographicItem }
17
+ # if document is found else returns NilClass
18
+ def get(code, year = nil, _opts = {})
19
+ warn "[relaton-ieee] (\"#{code}\") fetching..."
20
+ result = search(code) || (return nil)
21
+ year ||= code.match(/(?<=-)\d{4}/)&.to_s
22
+ ret = bib_results_filter(result, year)
23
+ if ret[:ret]
24
+ item = ret[:ret].fetch
25
+ warn "[relaton-ieee] (\"#{code}\") found #{item.docidentifier.first.id}"
26
+ item
27
+ else
28
+ fetch_ref_err(code, year, ret[:years])
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ # Sort through the results from RelatonIeee, fetching them three at a time,
35
+ # and return the first result that matches the code,
36
+ # matches the year (if provided), and which # has a title (amendments do not).
37
+ # Only expects the first page of results to be populated.
38
+ # Does not match corrigenda etc (e.g. ISO 3166-1:2006/Cor 1:2007)
39
+ # If no match, returns any years which caused mismatch, for error reporting
40
+ #
41
+ # @param result [RelatonIeee::HitCollection]
42
+ # @param opts [Hash] options
43
+ #
44
+ # @return [Hash]
45
+ def bib_results_filter(result, year)
46
+ missed_years = []
47
+ result.each do |hit|
48
+ return { ret: hit } if !year
49
+
50
+ return { ret: hit } if year.to_i == hit.hit[:year]
51
+
52
+ missed_years << hit.hit[:year]
53
+ end
54
+ { years: missed_years.uniq }
55
+ end
56
+
57
+ # @param code [Strig]
58
+ # @param year [String]
59
+ # @param missed_years [Array<Strig>]
60
+ def fetch_ref_err(code, year, missed_years)
61
+ id = year ? "#{code} year #{year}" : code
62
+ warn "[relaton-ieee] WARNING: no match found online for #{id}. "\
63
+ "The code must be exactly like it is on the standards website."
64
+ unless missed_years.empty?
65
+ warn "[relaton-ieee] (There was no match for #{year}, though there were matches "\
66
+ "found for #{missed_years.join(', ')}.)"
67
+ end
68
+ nil
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,41 @@
1
+ require "relaton/processor"
2
+
3
+ module RelatonIeee
4
+ class Processor < Relaton::Processor
5
+ attr_reader :idtype
6
+
7
+ def initialize
8
+ @short = :relaton_ieee
9
+ @prefix = "IEEE"
10
+ @defaultprefix = %r{^IEEE\s}
11
+ @idtype = "IEEE"
12
+ end
13
+
14
+ # @param code [String]
15
+ # @param date [String, NilClass] year
16
+ # @param opts [Hash]
17
+ # @return [RelatonIeee::IeeeBibliographicItem]
18
+ def get(code, date, opts)
19
+ ::RelatonIeee::IeeeBibliography.get(code, date, opts)
20
+ end
21
+
22
+ # @param xml [String]
23
+ # @return [RelatonIeee::IeeeBibliographicItem]
24
+ def from_xml(xml)
25
+ ::RelatonIeee::XMLParser.from_xml xml
26
+ end
27
+
28
+ # @param hash [Hash]
29
+ # @return [RelatonIeee::IeeeBibliographicItem]
30
+ def hash_to_bib(hash)
31
+ item_hash = ::RelatonIeee::HashConverter.hash_to_bib(hash)
32
+ ::RelatonIeee::IeeeBibliographicItem.new item_hash
33
+ end
34
+
35
+ # Returns hash of XML grammar
36
+ # @return [String]
37
+ def grammar_hash
38
+ @grammar_hash ||= ::RelatonIeee.grammar_hash
39
+ end
40
+ end
41
+ end