relaton-ieee 1.9.0 → 1.9.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: dc70675477b3d216a6e596b63c89e2fd867cb725372226d45fdd67da6d1f170e
4
- data.tar.gz: 0e24be2cab28dd83370e90e19fb3058432005a475f299c0d79eb216177a0054b
3
+ metadata.gz: 496eeef1c7a04e944fe7ea3133c6d6cf864039f5ce7d64ab049853818e2a8ac0
4
+ data.tar.gz: 5339c5f4b2871f24a112167ec07ad0a215b4fbf41410edaa623d7aec29d21574
5
5
  SHA512:
6
- metadata.gz: 05e9abb808f6517cfd8dd9f85b0b033594a8bbfb7c179f18e5db493c9b3afac4d9fb9adf902b32a5d7444791770894e449341c2cbfd4380a254cf232b01e41ac
7
- data.tar.gz: db0577970220cfcb39ca1b00083851a7d49630e61870d8e3cd2de330ac8ea5d8fe14c6c9afd6640662b9e04e05428acec4bda234b34f2f02527b32b125a62c7a
6
+ metadata.gz: 32755edbd38f6310f082de0302a02355abc8f641d4b21de794c321d9f244ee69f8536b6ee2e288d1020bf1885439f0071fa7da10ca1c3c9097cac00b3a7f5e75
7
+ data.tar.gz: 5afecd68a82cda36434bff25c4f0c9720e55e399fc26835c5924c6b57429798f7dc00aaeaaf136c65e9cb409fde4df7614b06015eec16d99406d0b6b3b9d34e0
data/.gitignore CHANGED
@@ -11,4 +11,5 @@
11
11
  .rspec_status
12
12
  .rubocop-https---raw-githubusercontent-com-riboseinc-oss-guides-master-ci-rubocop-yml
13
13
  .vscode/
14
+ ieee-rawbib/
14
15
  Gemfile.lock
data/README.adoc CHANGED
@@ -138,6 +138,16 @@ RelatonIeee::IeeeBibliography.get("IEEE 528-2019")
138
138
  ...
139
139
  ----
140
140
 
141
+ === Typed links
142
+
143
+ Each IEEE document has `src` type link.
144
+
145
+ [source,ruby]
146
+ ----
147
+ item.link
148
+ => [#<RelatonBib::TypedUri:0x00007fe885219ba0 @content=#<Addressable::URI:0x8ac URI:https://standards.ieee.org/standard/528-2019.html>, @type="src">]
149
+ ----
150
+
141
151
  === Create bibliographic item from XML
142
152
  [source,ruby]
143
153
  ----
@@ -158,6 +168,25 @@ hash = YAML.load_file 'spec/fixtures/ieee_528_2019.yaml'
158
168
  ...
159
169
  ----
160
170
 
171
+ === Fetch data
172
+
173
+ There is an IEEE dataset https://github.com/ietf-ribose/ieee-rawbib which can be converted into BibXML/BibYAML formats. The dataset needs to be placed into local directiory.
174
+
175
+ The method `RelatonIeee::DataFetcher.fetch(output: "data", format: "yaml")` converts all the documents from the local `ieee-rawbib` directory and save them to the `./data` folder in YAML format.
176
+ Arguments:
177
+
178
+ - `output` - folder to save documents (default './data').
179
+ - `format` - format in which the documents are saved. Possimle formats are: `yaml`, `xml` (default `yaml`).
180
+
181
+ [source,ruby]
182
+ ----
183
+ RelatonIeee::DataFetcher.fetch
184
+ Started at: 2021-09-24 17:55:07 +0200
185
+ Stopped at: 2021-09-24 17:57:30 +0200
186
+ Done in: 143 sec.
187
+ => nil
188
+ ----
189
+
161
190
  == Development
162
191
 
163
192
  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.
@@ -0,0 +1,14 @@
1
+ module RelatonIeee
2
+ module BibXMLParser
3
+ extend RelatonBib::BibXMLParser
4
+ extend BibXMLParser
5
+
6
+ FLAVOR = "IEEE".freeze
7
+
8
+ # @param attrs [Hash]
9
+ # @return [RelatonBib::IetfBibliographicItem]
10
+ def bib_item(**attrs)
11
+ IeeeBibliographicItem.new(**attrs)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,229 @@
1
+ require "zip"
2
+ require "relaton_ieee/data_parser"
3
+ require "relaton_ieee/rawbib_id_parser"
4
+
5
+ module RelatonIeee
6
+ class DataFetcher
7
+ RELATION_TYPES = {
8
+ "S" => { type: "obsoletedBy" },
9
+ "V" => { type: "updates", description: "revises" },
10
+ "T" => { type: "updates", description: "amends" },
11
+ "C" => { type: "updates", description: "corrects" },
12
+ "O" => { type: "adoptedFrom" },
13
+ "P" => { type: "complementOf", description: "supplement" },
14
+ "N" => false, "G" => false,
15
+ "F" => false, "I" => false,
16
+ "E" => false, "B" => false, "W" => false
17
+ }.freeze
18
+
19
+ # @return [Hash] list of AMSID => PubID
20
+ attr_reader :backrefs
21
+
22
+ #
23
+ # Create RelatonIeee::DataFetcher instance
24
+ #
25
+ # @param [String] output output dir
26
+ # @param [Strong] format output format. Allowed values: "yaml" or "xml"
27
+ #
28
+ def initialize(output, format)
29
+ @output = output
30
+ @format = format
31
+ @ext = format.sub(/^bib/, "")
32
+ @crossrefs = {}
33
+ @backrefs = {}
34
+ # @normtitles = []
35
+ end
36
+
37
+ #
38
+ # Convert documents from `ieee-rawbib` dir (IEEE dataset) to BibYAML/BibXML
39
+ #
40
+ # @param [String] output ('data') output dir
41
+ # @param [String] format ('yaml') output format.
42
+ # Allowed values: "yaml" or "xml"
43
+ #
44
+ def self.fetch(output: "data", format: "yaml")
45
+ t1 = Time.now
46
+ puts "Started at: #{t1}"
47
+ FileUtils.mkdir_p output unless Dir.exist? output
48
+ new(output, format).fetch
49
+ t2 = Time.now
50
+ puts "Stopped at: #{t2}"
51
+ puts "Done in: #{(t2 - t1).round} sec."
52
+ end
53
+
54
+ #
55
+ # Convert documents from `ieee-rawbib` dir (IEEE dataset) to BibYAML/BibXML
56
+ #
57
+ def fetch # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
58
+ Dir["ieee-rawbib/**/*.{xml,zip}"].reject { |f| f["Deleted_"] }.each do |f|
59
+ xml = case File.extname(f)
60
+ when ".zip" then read_zip f
61
+ when ".xml" then File.read f, encoding: "UTF-8"
62
+ end
63
+ fetch_doc xml, f
64
+ rescue StandardError => e
65
+ warn "File: #{f}"
66
+ warn e.message
67
+ warn e.backtrace
68
+ end
69
+ # File.write "normtitles.txt", @normtitles.join("\n")
70
+ update_relations
71
+ end
72
+
73
+ #
74
+ # Extract XML file from zip archive
75
+ #
76
+ # @param [String] file path to achive
77
+ #
78
+ # @return [String] file content
79
+ #
80
+ def read_zip(file)
81
+ Zip::File.open(file) do |zf|
82
+ entry = zf.glob("**/*.xml").first
83
+ entry.get_input_stream.read
84
+ end
85
+ end
86
+
87
+ #
88
+ # Parse document and save it
89
+ #
90
+ # @param [String] xml content
91
+ # @param [String] filename source file
92
+ #
93
+ def fetch_doc(xml, filename) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
94
+ doc = Nokogiri::XML(xml).at("/publication")
95
+ unless doc
96
+ warn "Empty file: #{filename}"
97
+ return
98
+ end
99
+ stdid = doc.at("./publicationinfo/standard_id").text
100
+ if stdid == "0"
101
+ # nt = doc&.at("./normtitle")&.text
102
+ # ntid = @normtitles.index nt
103
+ # @normtitles << nt if nt && !ntid
104
+ warn "Zero standard_id in #{filename}"
105
+ return
106
+ end
107
+ bib = DataParser.parse doc, self
108
+ if bib.docnumber.nil?
109
+ nt = doc&.at("./normtitle")&.text
110
+ warn "PubID parse error. Normtitle: #{nt}, file: #{filename}"
111
+ return
112
+ end
113
+ amsid = doc.at("./publicationinfo/amsid").text
114
+ if backrefs.value?(bib.docidentifier[0].id) && /updates\.\d+/ !~ filename
115
+ oamsid = backrefs.key bib.docidentifier[0].id
116
+ warn "Document exists ID: \"#{bib.docidentifier[0].id}\" AMSID: "\
117
+ "\"#{amsid}\" source: \"#{filename}\". Other AMSID: \"#{oamsid}\""
118
+ if bib.docidentifier[0].id.include?(doc.at("./publicationinfo/stdnumber").text)
119
+ save_doc bib # rewrite file if the PubID matches to the stdnumber
120
+ backrefs[amsid] = bib.docidentifier[0].id
121
+ end
122
+ else
123
+ save_doc bib
124
+ backrefs[amsid] = bib.docidentifier[0].id
125
+ end
126
+ end
127
+
128
+ #
129
+ # Save unresolved relation reference
130
+ #
131
+ # @param [String] docnumber of main document
132
+ # @param [Nokogiri::XML::Element] amsid relation data
133
+ #
134
+ def add_crossref(docnumber, amsid)
135
+ return if RELATION_TYPES[amsid[:type]] == false
136
+
137
+ ref = { amsid: amsid.text, type: amsid[:type] }
138
+ if @crossrefs[docnumber]
139
+ @crossrefs[docnumber] << ref
140
+ else @crossrefs[docnumber] = [ref]
141
+ end
142
+ end
143
+
144
+ #
145
+ # Save document to file
146
+ #
147
+ # @param [RelatonIeee::IeeeBibliographicItem] bib
148
+ #
149
+ def save_doc(bib)
150
+ c = case @format
151
+ when "xml" then bib.to_xml(bibdata: true)
152
+ when "yaml" then bib.to_hash.to_yaml
153
+ else bib.send("to_#{@format}")
154
+ end
155
+ File.write file_name(bib.docnumber), c, encoding: "UTF-8"
156
+ end
157
+
158
+ #
159
+ # Make filename from PubID
160
+ #
161
+ # @param [String] docnumber
162
+ #
163
+ # @return [String] filename
164
+ #
165
+ def file_name(docnumber)
166
+ name = docnumber.gsub(/\s-/, "-").gsub(/[\s,:\/]/, "_").squeeze("_").upcase
167
+ File.join @output, "#{name}.#{@ext}"
168
+ end
169
+
170
+ #
171
+ # Update unresoverd relations
172
+ #
173
+ def update_relations # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
174
+ @crossrefs.each do |dnum, rfs|
175
+ bib = nil
176
+ rfs.each do |rf|
177
+ if backrefs[rf[:amsid]]
178
+ rel = create_relation(rf[:type], backrefs[rf[:amsid]])
179
+ if rel
180
+ bib ||= read_bib(dnum)
181
+ bib.relation << rel
182
+ save_doc bib
183
+ end
184
+ else
185
+ warn "Unresolved relation: '#{rf[:amsid]}' type: '#{rf[:type]}' for '#{dnum}'"
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ #
192
+ # Create relation instance
193
+ #
194
+ # @param [String] type IEEE relation type
195
+ # @param [String] fref reference
196
+ #
197
+ # @return [RelatonBib::DocumentRelation]
198
+ #
199
+ def create_relation(type, fref)
200
+ return if RELATION_TYPES[type] == false
201
+
202
+ fr = RelatonBib::FormattedRef.new(content: fref)
203
+ bib = IeeeBibliographicItem.new formattedref: fr
204
+ desc = RELATION_TYPES[type][:description]
205
+ description = desc && RelatonBib::FormattedString.new(content: desc, language: "en", script: "Latn")
206
+ RelatonBib::DocumentRelation.new(
207
+ type: RELATION_TYPES[type][:type],
208
+ description: description,
209
+ bibitem: bib,
210
+ )
211
+ end
212
+
213
+ #
214
+ # Read document form BibXML/BibYAML file
215
+ #
216
+ # @param [String] docnumber
217
+ #
218
+ # @return [RelatonIeee::IeeeBibliographicItem]
219
+ #
220
+ def read_bib(docnumber)
221
+ c = File.read file_name(docnumber), encoding: "UTF-8"
222
+ case @format
223
+ when "xml" then XMLParser.from_xml c
224
+ when "bibxml" then BibXMLParser.parse c
225
+ else IeeeBibliographicItem.from_hash YAML.safe_load(c)
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,278 @@
1
+ module RelatonIeee
2
+ class DataParser
3
+ DATETYPES = { "OriginalPub" => "created", "ePub" => "published",
4
+ "LastInspecUpd" => "updated" }.freeze
5
+
6
+ attr_reader :doc, :fetcher
7
+
8
+ #
9
+ # Create RelatonIeee::DataParser instance
10
+ #
11
+ # @param [Nokogiri::XML::Element] doc document
12
+ # @param [RelatonIeee::DataFetcher] fetcher
13
+ #
14
+ def initialize(doc, fetcher)
15
+ @doc = doc
16
+ @fetcher = fetcher
17
+ end
18
+
19
+ #
20
+ # Parse IEEE document
21
+ #
22
+ # @param [Nokogiri::XML::Element] doc document
23
+ # @param [RelatonIeee::DataFetcher] fetcher <description>
24
+ #
25
+ # @return [RelatonIeee::IeeeBibliographicItem]
26
+ #
27
+ def self.parse(doc, fetcher)
28
+ new(doc, fetcher).parse
29
+ end
30
+
31
+ #
32
+ # Parse IEEE document
33
+ #
34
+ # @return [RelatonIeee::IeeeBibliographicItem]
35
+ #
36
+ def parse # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
37
+ args = {
38
+ type: "standard",
39
+ docnumber: docnumber,
40
+ title: parse_title,
41
+ date: parse_date,
42
+ docid: parse_docid,
43
+ contributor: parse_contributor,
44
+ abstract: parse_abstract,
45
+ copyright: parse_copyright,
46
+ language: ["en"],
47
+ script: ["Latn"],
48
+ status: parse_status,
49
+ relation: parse_relation,
50
+ link: parse_link,
51
+ keyword: parse_keyword,
52
+ ics: parse_ics,
53
+ }
54
+ IeeeBibliographicItem.new(**args)
55
+ end
56
+
57
+ #
58
+ # Parse title
59
+ #
60
+ # @return [Array<RelatonBib::TypedTitleString>]
61
+ #
62
+ def parse_title
63
+ t = []
64
+ content = doc.at("./volume/article/title").text
65
+ if content =~ /\A(.+)\s-\sredline\z/i
66
+ t << RelatonBib::TypedTitleString.new(content: $1, type: "title-main")
67
+ end
68
+ t << RelatonBib::TypedTitleString.new(content: content, type: "main")
69
+ end
70
+
71
+ #
72
+ # Parse date
73
+ #
74
+ # @return [Array<RelatonBib::BibliographicDate>]
75
+ #
76
+ def parse_date # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
77
+ dates = doc.xpath("./volume/article/articleinfo/date").map do |d|
78
+ da = [d.at("./year").text]
79
+ m = d.at("./month")&.text
80
+ if m
81
+ month = Date::ABBR_MONTHNAMES.index(m.sub(/\./, "")) || m
82
+ da << month.to_s.rjust(2, "0")
83
+ end
84
+ day = d.at("./day")
85
+ da << day.text.rjust(2, "0") if day
86
+ on = da.compact.join "-"
87
+ RelatonBib::BibliographicDate.new type: DATETYPES[d[:datetype]], on: on
88
+ end
89
+ pad = doc.at("./publicationinfo/PubApprovalDate")
90
+ if pad
91
+ issued = parse_date_string pad.text
92
+ dates << RelatonBib::BibliographicDate.new(type: "issued", on: issued)
93
+ end
94
+ dates
95
+ end
96
+
97
+ #
98
+ # Convert date string with month name to numeric date
99
+ #
100
+ # @param [String] date source date
101
+ #
102
+ # @return [String] numeric date
103
+ #
104
+ def parse_date_string(date)
105
+ case date
106
+ when /^\d{4}$/ then date
107
+ when /^\d{1,2}\s\w+\.?\s\d{4}/ then Date.parse(date).to_s
108
+ end
109
+ end
110
+
111
+ #
112
+ # Parse identifiers
113
+ #
114
+ # @return [Array<RelatonBib::DocumentIdentifier>]
115
+ #
116
+ def parse_docid
117
+ ids = [{ id: pubid.to_s, type: "IEEE" }]
118
+ isbn = doc.at("./publicationinfo/isbn")
119
+ ids << { id: isbn.text, type: "ISBN" } if isbn
120
+ doi = doc.at("./volume/article/articleinfo/articledoi")
121
+ ids << { id: doi.text, type: "DOI" } if doi
122
+ ids.map do |dcid|
123
+ RelatonBib::DocumentIdentifier.new(**dcid)
124
+ end
125
+ end
126
+
127
+ def pubid
128
+ @pubid ||= begin
129
+ nt = doc.at("./normtitle").text
130
+ RawbibIdParser.parse(nt)
131
+ end
132
+ end
133
+
134
+ #
135
+ # Parse docnumber
136
+ #
137
+ # @return [String] PubID
138
+ #
139
+ def docnumber
140
+ @docnumber ||= pubid&.to_id # doc.at("./publicationinfo/stdnumber").text
141
+ end
142
+
143
+ #
144
+ # Parse contributors
145
+ #
146
+ # @return [Array<RelatonBib::ContributionInfo>]
147
+ #
148
+ def parse_contributor # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
149
+ doc.xpath("./publicationinfo/publisher").map do |contrib|
150
+ n = contrib.at("./publishername").text
151
+ addr = contrib.xpath("./address").map do |a|
152
+ RelatonBib::Address.new(
153
+ street: [],
154
+ city: a.at("./city")&.text,
155
+ country: a.at("./country").text,
156
+ )
157
+ end
158
+ e = create_org n, addr
159
+ RelatonBib::ContributionInfo.new entity: e, role: [type: "publisher"]
160
+ end
161
+ end
162
+
163
+ #
164
+ # Create organization
165
+ #
166
+ # @param [String] name organization's name
167
+ # @param [Array<Hash>] addr address
168
+ #
169
+ # @return [RelatonBib::Organization]
170
+ def create_org(name, addr = []) # rubocop:disable Metrics/MethodLength
171
+ case name
172
+ when "IEEE"
173
+ abbr = name
174
+ n = "Institute of Electrical and Electronics Engineers"
175
+ url = "http://www.ieee.org"
176
+ when "ANSI"
177
+ abbr = name
178
+ n = "American National Standards Institute"
179
+ url = "https://www.ansi.org"
180
+ else n = name
181
+ end
182
+ RelatonBib::Organization.new(
183
+ name: n, abbreviation: abbr, url: url, contact: addr,
184
+ )
185
+ end
186
+
187
+ #
188
+ # Parse abstract
189
+ #
190
+ # @return [Array<RelatonBib::FormattedString>]
191
+ #
192
+ def parse_abstract
193
+ doc.xpath("./volume/article/articleinfo/abstract").map do |a|
194
+ RelatonBib::FormattedString.new(
195
+ content: a.text, language: "en", script: "Latn",
196
+ )
197
+ end
198
+ end
199
+
200
+ #
201
+ # Parse copyright
202
+ #
203
+ # @return [Array<RelatonBib::CopyrightAssociation>]
204
+ #
205
+ def parse_copyright
206
+ doc.xpath("./publicationinfo/copyrightgroup/copyright").map do |c|
207
+ owner = c.at("./holder").text.split("/").map do |own|
208
+ RelatonBib::ContributionInfo.new entity: create_org(own)
209
+ end
210
+ RelatonBib::CopyrightAssociation.new(
211
+ owner: owner, from: c.at("./year").text,
212
+ )
213
+ end
214
+ end
215
+
216
+ #
217
+ # Parse status
218
+ #
219
+ # @return [RelatonBib::DocumentStatus]
220
+ #
221
+ def parse_status
222
+ stage = doc.at("./publicationinfo/standard_status").text
223
+ RelatonBib::DocumentStatus.new stage: stage
224
+ end
225
+
226
+ #
227
+ # Parse relation
228
+ #
229
+ # @return [RelatonBib::DocRelationCollection]
230
+ #
231
+ def parse_relation # rubocop:disable Metrics/AbcSize
232
+ rels = []
233
+ doc.xpath("./publicationinfo/standard_relationship").each do |r|
234
+ if (ref = fetcher.backrefs[r.text])
235
+ rel = fetcher.create_relation(r[:type], ref)
236
+ rels << rel if rel
237
+ elsif !/Inactive Date/.match?(r) && docnumber
238
+ fetcher.add_crossref(docnumber, r)
239
+ end
240
+ end
241
+ RelatonBib::DocRelationCollection.new rels
242
+ end
243
+
244
+ #
245
+ # Parce link
246
+ #
247
+ # @return [Array<RelatonBib::TypedUri>]
248
+ #
249
+ def parse_link
250
+ doc.xpath("./volume/article/articleinfo/amsid").map do |id|
251
+ l = "https://ieeexplore.ieee.org/document/#{id.text}"
252
+ RelatonBib::TypedUri.new content: l, type: "src"
253
+ end
254
+ end
255
+
256
+ #
257
+ # Parse keyword
258
+ #
259
+ # @return [Array<Strign>]
260
+ #
261
+ def parse_keyword
262
+ doc.xpath(
263
+ "./volume/article/articleinfo/keywordset/keyword/keywordterm",
264
+ ).map &:text
265
+ end
266
+
267
+ #
268
+ # Parse ICS
269
+ #
270
+ # @return [Array<RelatonBib::ICS>]
271
+ #
272
+ def parse_ics
273
+ doc.xpath("./publicationinfo/icscodes/code_term").map do |ics|
274
+ RelatonBib::ICS.new code: ics[:codenum], text: ics.text
275
+ end
276
+ end
277
+ end
278
+ end
@@ -5,7 +5,7 @@ module RelatonIeee
5
5
 
6
6
  # @param committee [Array<RelatonIeee::Committee>]
7
7
  def initialize(**args)
8
- @committee = args.delete :committee
8
+ @committee = args.delete(:committee) || []
9
9
  super
10
10
  end
11
11
 
@@ -13,7 +13,7 @@ module RelatonIeee
13
13
  # @return [RelatonIeee::IeeeBibliographicItem]
14
14
  def self.from_hash(hash)
15
15
  item_hash = ::RelatonIeee::HashConverter.hash_to_bib(hash)
16
- new **item_hash
16
+ new(**item_hash)
17
17
  end
18
18
 
19
19
  # @param opts [Hash]
@@ -22,7 +22,7 @@ module RelatonIeee
22
22
  # @option opts [String] :lang language
23
23
  # @return [String] XML
24
24
  def to_xml(**opts)
25
- super **opts do |bldr|
25
+ super(**opts) do |bldr|
26
26
  if opts[:bibdata] && committee.any?
27
27
  bldr.ext do |b|
28
28
  committee.each { |c| c.to_xml b }
@@ -34,7 +34,7 @@ module RelatonIeee
34
34
  # @return [Hash]
35
35
  def to_hash
36
36
  hash = super
37
- hash["committee"] = committee.map &:to_hash
37
+ hash["committee"] = committee.map &:to_hash if committee.any?
38
38
  hash
39
39
  end
40
40
 
@@ -19,7 +19,7 @@ module RelatonIeee
19
19
  warn "[relaton-ieee] (\"#{code}\") fetching..."
20
20
  result = search(code) || (return nil)
21
21
  year ||= code.match(/(?<=-)\d{4}/)&.to_s
22
- ret = bib_results_filter(result, year)
22
+ ret = bib_results_filter(result, code, year)
23
23
  if ret[:ret]
24
24
  item = ret[:ret].fetch
25
25
  warn "[relaton-ieee] (\"#{code}\") found #{item.docidentifier.first.id}"
@@ -42,9 +42,13 @@ module RelatonIeee
42
42
  # @param opts [Hash] options
43
43
  #
44
44
  # @return [Hash]
45
- def bib_results_filter(result, year)
45
+ def bib_results_filter(result, ref, year)
46
+ rp1 = ref_parts ref
46
47
  missed_years = []
47
48
  result.each do |hit|
49
+ rp2 = ref_parts hit.hit["recordTitle"]
50
+ next if rp1[:code] != rp2[:code] || rp1[:corr] != rp2[:corr]
51
+
48
52
  return { ret: hit } if !year
49
53
 
50
54
  return { ret: hit } if year.to_i == hit.hit[:year]
@@ -54,6 +58,15 @@ module RelatonIeee
54
58
  { years: missed_years.uniq }
55
59
  end
56
60
 
61
+ def ref_parts(ref)
62
+ %r{
63
+ ^(?:IEEE\s(?:Std\s)?)?
64
+ (?<code>[^-/]+)
65
+ (?:-(?<year>\d{4}))?
66
+ (?:/(?<corr>\w+\s\d+-\d{4}))?
67
+ }x.match ref
68
+ end
69
+
57
70
  # @param code [Strig]
58
71
  # @param year [String]
59
72
  # @param missed_years [Array<Strig>]
@@ -4,11 +4,12 @@ module RelatonIeee
4
4
  class Processor < Relaton::Processor
5
5
  attr_reader :idtype
6
6
 
7
- def initialize
7
+ def initialize # rubocop:disable Lint/MissingSuper
8
8
  @short = :relaton_ieee
9
9
  @prefix = "IEEE"
10
10
  @defaultprefix = %r{^IEEE\s}
11
11
  @idtype = "IEEE"
12
+ @datasets = %w[ieee-rawbib]
12
13
  end
13
14
 
14
15
  # @param code [String]
@@ -19,6 +20,18 @@ module RelatonIeee
19
20
  ::RelatonIeee::IeeeBibliography.get(code, date, opts)
20
21
  end
21
22
 
23
+ #
24
+ # Fetch all the documents from ./iee-rawbib directory
25
+ #
26
+ # @param [String] _source source name
27
+ # @param [Hash] opts
28
+ # @option opts [String] :output directory to output documents
29
+ # @option opts [String] :format
30
+ #
31
+ def fetch_data(_source, opts)
32
+ DataFetcher.fetch(**opts)
33
+ end
34
+
22
35
  # @param xml [String]
23
36
  # @return [RelatonIeee::IeeeBibliographicItem]
24
37
  def from_xml(xml)