ebsco-discovery-service-api 1.1.10 → 1.1.12

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDQ0ZGI2ZDFjYzkzYzk1MDM0ODhhOTQ5Y2YzMDE5YjZkZGQzY2FjMw==
4
+ NzMzM2U3MTFlNzlkNzA4NzlkNWJkYzM3ZDdjMTZmZjI5MDJiNGY5NQ==
5
5
  data.tar.gz: !binary |-
6
- MjgwZTI5Nzg5MDJiZWI2MzI4ZGM0ZWE1YTQyZmJhOWE0Yzg0MmYwZg==
6
+ OTlmY2E0MWU5MTJiMjlkN2U3ZDE3NmFlOTFjNzU0MmJlZTYzOWI2NQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTUxODY2NjJmNDhhYjAxOWNlZjAzNWM3YjBhODhlN2EyZjg2Y2I4YjBkMzJi
10
- YTAwMGRjYmZhMmQ0OTlkMDMyNTNhNDBhZjUwNGIzZTk5YjdhOGJiNzIwNDgz
11
- Nzk0MDBhODFjODA1NTRiMmFlOTg5YTg2OTQ2NTgwY2Y1NDhhZDc=
9
+ NjkyOGNlOWYxMzViMGRmOWI2Mjk5NTM5ZjJjM2MzYWQzOWIzMDAxYmQxYTll
10
+ NTIxNDgxZTU5YTcwYzA2OTI1YmZmZGM3YmJmZjg2M2ZhMGY0YTM3OGFjYzI5
11
+ OWJmNWQzYmU0YTg4ZTlhMWEzOGE0ZWZhYWMxMDgxZjc4YjJiNWY=
12
12
  data.tar.gz: !binary |-
13
- OGYzZDhlNjZmNTJkNTc2NmNmMzM0YjgwZGEzYjM5ZGZhYWFmNDIxODNiMTkw
14
- NjEwYThmNGRkYjU1ZDRlMzJmZTZiODdlMDAyNmIwNWFlODRkNmNiYzI1OWJl
15
- ODU0MDU2N2I4MmJjZTczYTE5YjgxYmNhNThmYWNiZTgyNTgzNzI=
13
+ ZjE2MTQ4MWE3NzYzZmM1M2JkMWJhOTFjMGM1NjE2ODY1MDgzM2UyNjJkZWFh
14
+ MWEwMzljOTExYTE3MTNjNDc1OWZjMWFjNTI2ZDI5YjE0MTkwOWVlYjdlZGI1
15
+ Njc0MDA3NGY4NzgwZWQwYmMxNTIyMThjNzNjNzdlMzQ2NDRmODg=
@@ -2,21 +2,932 @@ require 'net/http'
2
2
  require 'cgi'
3
3
  require 'json'
4
4
 
5
- # This is the first, barely tested pass at creating a set of Ruby functions to authenticate to, search, and retrieve from the EDS API.
6
- # Once this gem is installed, you can find demo code that makes use of the gem here:
7
- # http://www.lh2cc.net/dse/efrierson/ruby/eds-alpha-demo.zip
5
+ #TO DO: Finish publication Exact Match object - probably needs to be a subclass of EDSAPIRecord
6
+ #TO DO: Finish Detailed Records
8
7
 
9
8
  module EDSApi
10
-
9
+
11
10
  API_URL = "http://eds-api.ebscohost.com/"
12
11
  API_URL_S = "https://eds-api.ebscohost.com/"
13
-
12
+
13
+ DB_LABEL_LOOKUP = {}
14
+ DB_LABEL_LOOKUP["EDB"] = "Publisher Provided Full Text Searching File"
15
+ DB_LABEL_LOOKUP["EDO"] = "Supplemental Index"
16
+ DB_LABEL_LOOKUP["ASX"] = "Academic Search Index"
17
+ DB_LABEL_LOOKUP["A9H"] = "Academic Search Complete"
18
+ DB_LABEL_LOOKUP["APH"] = "Academic Search Premier"
19
+ DB_LABEL_LOOKUP["AFH"] = "Academic Search Elite"
20
+ DB_LABEL_LOOKUP["A2H"] = "Academic Search Alumni Edition"
21
+ DB_LABEL_LOOKUP["ASM"] = "Academic Search Main Edition"
22
+ DB_LABEL_LOOKUP["ASR"] = "STM Source"
23
+ DB_LABEL_LOOKUP["BSX"] = "Business Source Index"
24
+ DB_LABEL_LOOKUP["EDSEBK"] = "Discovery eBooks"
25
+ DB_LABEL_LOOKUP["VTH"] = "Art & Architecture Complete"
26
+ DB_LABEL_LOOKUP["IIH"] = "Computers & Applied Sciences Complete"
27
+ DB_LABEL_LOOKUP["CMH"] = "Consumer Health Complete - CHC Platform"
28
+ DB_LABEL_LOOKUP["C9H"] = "Consumer Health Complete - EBSCOhost"
29
+ DB_LABEL_LOOKUP["EOAH"] = "E-Journals Database"
30
+ DB_LABEL_LOOKUP["EHH"] = "Education Research Complete"
31
+ DB_LABEL_LOOKUP["HCH"] = "Health Source: Nursing/Academic"
32
+ DB_LABEL_LOOKUP["HXH"] = "Health Source: Consumer Edition"
33
+ DB_LABEL_LOOKUP["HLH"] = "Humanities International Complete"
34
+ DB_LABEL_LOOKUP["LGH"] = "Legal Collection"
35
+ DB_LABEL_LOOKUP["SLH"] = "Sociological Collection"
36
+ DB_LABEL_LOOKUP["CPH"] = "Computer Source"
37
+ DB_LABEL_LOOKUP["PBH"] = "Psychology & Behavioral Sciences Collection"
38
+ DB_LABEL_LOOKUP["RLH"] = "Religion & Philosophy Collection"
39
+ DB_LABEL_LOOKUP["NFH"] = "Newspaper Source"
40
+ DB_LABEL_LOOKUP["N5H"] = "Newspaper Source Plus"
41
+ DB_LABEL_LOOKUP["BWH"] = "Regional Business News"
42
+ DB_LABEL_LOOKUP["OFM"] = "OmniFile Full Text Mega"
43
+ DB_LABEL_LOOKUP["RSS"] = "Rehabilitation & Sports Medicine Source"
44
+ DB_LABEL_LOOKUP["SYH"] = "Science & Technology Collection"
45
+ DB_LABEL_LOOKUP["SCF"] = "Science Full Text Select"
46
+ DB_LABEL_LOOKUP["HEH"] = "Health Business Elite"
47
+
48
+ class EDSAPIRecord
49
+
50
+ attr_accessor :record
51
+
52
+ def initialize(results_record)
53
+ @record = results_record;
54
+ end
55
+
56
+ def resultid
57
+ @record["ResultId"]
58
+ end
59
+
60
+ def an
61
+ @record["Header"]["An"].to_s
62
+ end
63
+
64
+ def dbid
65
+ @record["Header"]["DbId"].to_s
66
+ end
67
+
68
+ def plink
69
+ @record["Header"]["PLink"]
70
+ end
71
+
72
+ def score
73
+ @record["Header"]["RelevancyScore"]
74
+ end
75
+
76
+ def pubtype
77
+ @record["Header"]["PubType"]
78
+ end
79
+
80
+ def pubtype_id
81
+ @record["Header"]["PubTypeId"]
82
+ end
83
+
84
+ def db_label
85
+ if DB_LABEL_LOOKUP.key?(self.dbid.upcase)
86
+ dblabel = DB_LABEL_LOOKUP[self.dbid.upcase];
87
+ else
88
+ dblabel = @record["Header"]["DbLabel"]
89
+ end
90
+ end
91
+
92
+ def images (size_requested = "all")
93
+ returned_images = []
94
+
95
+ images = @record.fetch('ImageInfo', {})
96
+ if images.count > 0
97
+ images.each do |image|
98
+ if size_requested == image["Size"] || size_requested == "all"
99
+ returned_images.push({size: image["Size"], src: image["Target"]})
100
+ end
101
+ end
102
+ end
103
+ return returned_images
104
+ end
105
+
106
+ def title
107
+ items = @record.fetch('Items',{})
108
+ if items.count > 0
109
+ items.each do |item|
110
+ if item["Group"] == "Ti"
111
+ return item["Data"]
112
+ end
113
+ end
114
+ end
115
+
116
+ titles = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Titles', {})
117
+ if titles.count > 0
118
+ titles.each do |title|
119
+ if title["Type"] == "main"
120
+ return title["TitleFull"]
121
+ end
122
+ end
123
+ end
124
+
125
+ return nil
126
+ end
127
+
128
+ def title_raw
129
+ titles = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Titles', {})
130
+ if titles.count > 0
131
+ titles.each do |title|
132
+ if title["Type"] == "main"
133
+ return title["TitleFull"]
134
+ end
135
+ end
136
+ end
137
+ items = @record.fetch('Items',{})
138
+ if items.count > 0
139
+ items.each do |item|
140
+ if item["Group"] == "Ti"
141
+ return item["Data"]
142
+ end
143
+ end
144
+ end
145
+ return nil
146
+ end
147
+ #end title_raw
148
+
149
+ def authors
150
+
151
+ items = @record.fetch('Items',{})
152
+ if items.count > 0
153
+ items.each do |item|
154
+ if item["Group"] == "Au"
155
+ return item["Data"]
156
+ end
157
+ end
158
+ end
159
+
160
+ contributors = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('HasContributorRelationships', {})
161
+
162
+ if contributors.count > 0
163
+ authors = []
164
+ contributors.each do |contributor|
165
+ names = contributor.fetch('PersonEntity',{})
166
+ authors.push(names['Name']['NameFull'])
167
+ end
168
+ author_str = authors.join("; ")
169
+ return author_str
170
+ end
171
+
172
+ return nil
173
+ end
174
+
175
+ def authors_raw
176
+
177
+ contributors = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('HasContributorRelationships', {})
178
+
179
+ if contributors.count > 0
180
+ authors = []
181
+ contributors.each do |contributor|
182
+ names = contributor.fetch('PersonEntity',{})
183
+ authors.push(names['Name']['NameFull'])
184
+ end
185
+ return authors
186
+ end
187
+
188
+ items = @record.fetch('Items',{})
189
+ if items.count > 0
190
+ items.each do |item|
191
+ if item["Group"] == "Au"
192
+ return [item["Data"]]
193
+ end
194
+ end
195
+ end
196
+
197
+ return []
198
+ end
199
+
200
+
201
+ def subjects
202
+
203
+ items = @record.fetch('Items',{})
204
+ if items.count > 0
205
+ items.each do |item|
206
+ if item["Group"] == "Su"
207
+ return item["Data"]
208
+ end
209
+ end
210
+ end
211
+
212
+ subjects = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Subjects', {})
213
+
214
+ if subjects.count > 0
215
+ subs = []
216
+ subjects.each do |subject|
217
+ subs.push(subject["SubjectFull"])
218
+ end
219
+ subs_str = subs.join("; ")
220
+ return subs_str
221
+ end
222
+
223
+ return nil
224
+ end
225
+
226
+ def subjects_raw
227
+
228
+ subjects = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Subjects', {})
229
+
230
+ if subjects.count > 0
231
+ subs = []
232
+ subjects.each do |subject|
233
+ subs.push(subject)
234
+ end
235
+ return subs
236
+ end
237
+
238
+ items = @record.fetch('Items',{})
239
+ if items.count > 0
240
+ items.each do |item|
241
+ if item["Group"] == "Su"
242
+ return [item["Data"]]
243
+ end
244
+ end
245
+ end
246
+
247
+ return []
248
+ end
249
+
250
+ def languages
251
+ language_section = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Languages', {})
252
+
253
+ if language_section.count > 0
254
+ langs = []
255
+ language_section.each do |language|
256
+ langs.push(language["Text"])
257
+ end
258
+ return langs
259
+ end
260
+ return []
261
+ end
262
+
263
+ def pages
264
+ pagination_section = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('PhysicalDescription', {})
265
+
266
+ if pagination_section.count > 0
267
+ return pagination_section["Pagination"]
268
+ end
269
+ return {}
270
+ end
271
+
272
+ def abstract
273
+ items = @record.fetch('Items',{})
274
+ if items.count > 0
275
+ items.each do |item|
276
+ if item["Group"] == "Ab"
277
+ return item["Data"]
278
+ end
279
+ end
280
+ end
281
+
282
+ return nil
283
+ end
284
+
285
+ def html_fulltext
286
+ htmlfulltextcheck = @record.fetch('FullText',{}).fetch('Text',{}).fetch('Availability',0)
287
+ if htmlfulltextcheck == "1"
288
+ return @record.fetch('FullText',{}).fetch('Text',{})["Value"]
289
+ end
290
+ return nil
291
+ end
292
+
293
+ def source
294
+
295
+ items = @record.fetch('Items',{})
296
+ if items.count > 0
297
+ items.each do |item|
298
+ if item["Group"] == "Src"
299
+ return item["Data"]
300
+ end
301
+ end
302
+ end
303
+
304
+ return nil
305
+ end
306
+
307
+ def source_title
308
+
309
+ unless self.source.nil?
310
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
311
+
312
+ if ispartof.count > 0
313
+ ispartof.each do |contributor|
314
+ titles = contributor.fetch('BibEntity',{}).fetch('Titles',{})
315
+ titles.each do |title_src|
316
+ if title_src["Type"] == "main"
317
+ return title_src["TitleFull"]
318
+ end
319
+ end
320
+ end
321
+ end
322
+ end
323
+ return nil
324
+
325
+ end
326
+
327
+ def numbering
328
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
329
+
330
+ if ispartof.count > 0
331
+ numbering = []
332
+ ispartof.each do |contributor|
333
+ nums = contributor.fetch('BibEntity',{}).fetch('Numbering',{})
334
+ nums.each do |num|
335
+ numbering.push(num)
336
+ end
337
+ end
338
+ return numbering
339
+ end
340
+
341
+ return []
342
+ end
343
+
344
+ def doi
345
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibEntity', {}).fetch('Identifiers', {})
346
+
347
+ if ispartof.count > 0
348
+ ispartof.each do |ids|
349
+ if ids["Type"] == "doi"
350
+ return ids["Value"]
351
+ end
352
+ end
353
+ end
354
+
355
+ return nil
356
+ end
357
+
358
+ def isbns
359
+
360
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
361
+
362
+ if ispartof.count > 0
363
+ issns = []
364
+ ispartof.each do |part_of|
365
+ ids = part_of.fetch('BibEntity',{}).fetch('Identifiers',{})
366
+ ids.each do |id|
367
+ if id["Type"].include?("isbn") && !id["Type"].include?("locals")
368
+ issns.push(id)
369
+ end
370
+ end
371
+ end
372
+ return issns
373
+ end
374
+ return []
375
+ end
376
+
377
+ def issns
378
+
379
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
380
+
381
+ if ispartof.count > 0
382
+ issns = []
383
+ ispartof.each do |part_of|
384
+ ids = part_of.fetch('BibEntity',{}).fetch('Identifiers',{})
385
+ ids.each do |id|
386
+ if id["Type"].include?("issn") && !id["Type"].include?("locals")
387
+ issns.push(id)
388
+ end
389
+ end
390
+ end
391
+ return issns
392
+ end
393
+ return []
394
+ end
395
+
396
+ def source_isbn
397
+ unless self.source.nil?
398
+
399
+ ispartof = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
400
+
401
+ if ispartof.count > 0
402
+ issns = []
403
+ ispartof.each do |part_of|
404
+ ids = part_of.fetch('BibEntity',{}).fetch('Identifiers',{})
405
+ ids.each do |id|
406
+ if id["Type"].include?("isbn") && !id["Type"].include?("locals")
407
+ issns.push(id)
408
+ end
409
+ end
410
+ end
411
+ return issns
412
+ end
413
+ end
414
+ return []
415
+ end
416
+
417
+
418
+
419
+ def pubyear
420
+ ispartofs = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
421
+ if ispartofs.count > 0
422
+ dates = ispartofs[0]["BibEntity"].fetch('Dates',{})
423
+ if dates.count > 0
424
+ dates.each do |date|
425
+ if date["Type"] == "published"
426
+ return date["Y"]
427
+ end
428
+ end
429
+ end
430
+ end
431
+ return nil
432
+ end
433
+
434
+ def pubdate
435
+ ispartofs = @record.fetch('RecordInfo', {}).fetch('BibRecord', {}).fetch('BibRelationships', {}).fetch('IsPartOfRelationships', {})
436
+ if ispartofs.count > 0
437
+ dates = ispartofs[0]["BibEntity"].fetch('Dates',{})
438
+ if dates.count > 0
439
+ dates.each do |date|
440
+ if date["Type"] == "published"
441
+ return date["Y"]+"-"+date["M"]+"-"+date["D"]
442
+ end
443
+ end
444
+ end
445
+ end
446
+ return nil
447
+ end
448
+
449
+ def all_links
450
+ links = self.fulltext_links
451
+ links = links + self.nonfulltext_links
452
+ return links
453
+ end
454
+
455
+ def fulltext_links
456
+
457
+ links = []
458
+
459
+ ebscolinks = @record.fetch('FullText',{}).fetch('Links',{})
460
+ if ebscolinks.count > 0
461
+ ebscolinks.each do |ebscolink|
462
+ if ebscolink["Type"] == "pdflink"
463
+ link_label = "PDF Full Text"
464
+ link_icon = "PDF Full Text Icon"
465
+ if ebscolink.key?("Url")
466
+ link_url = ebscolink["Url"]
467
+ else
468
+ link_url = "detail";
469
+ end
470
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "pdf"})
471
+ end
472
+ end
473
+ end
474
+
475
+ htmlfulltextcheck = @record.fetch('FullText',{}).fetch('Text',{}).fetch('Availability',0)
476
+ if htmlfulltextcheck == "1"
477
+ link_url = "detail"
478
+ link_label = "Full Text in Browser"
479
+ link_icon = "Full Text in Browser Icon"
480
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "html"})
481
+ end
482
+
483
+ if ebscolinks.count > 0
484
+ ebscolinks.each do |ebscolink|
485
+ if ebscolink["Type"] == "ebook-pdf"
486
+ link_label = "PDF eBook Full Text"
487
+ link_icon = "PDF eBook Full Text Icon"
488
+ if ebscolink.key?("Url")
489
+ link_url = ebscolink["Url"]
490
+ else
491
+ link_url = "detail";
492
+ end
493
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "ebook-pdf"})
494
+ end
495
+ end
496
+ end
497
+
498
+ if ebscolinks.count > 0
499
+ ebscolinks.each do |ebscolink|
500
+ if ebscolink["Type"] == "ebook-epub"
501
+ link_label = "ePub eBook Full Text"
502
+ link_icon = "ePub eBook Full Text Icon"
503
+ if ebscolink.key?("Url")
504
+ link_url = ebscolink["Url"]
505
+ else
506
+ link_url = "detail";
507
+ end
508
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "ebook-epub"})
509
+ end
510
+ end
511
+ end
512
+
513
+ items = @record.fetch('Items',{})
514
+ if items.count > 0
515
+ items.each do |item|
516
+ if item["Group"] == "URL"
517
+ if item["Data"].include? "linkTerm=""
518
+ link_start = item["Data"].index("linkTerm="")+15;
519
+ link_url = item["Data"][link_start..-1]
520
+ link_end = link_url.index(""")-1
521
+ link_url = link_url[0..link_end]
522
+ link_label_start = item["Data"].index("link>")+8
523
+ link_label = item["Data"][link_label_start..-1]
524
+ link_label = link_label.strip
525
+ else
526
+ link_url = item["Data"]
527
+ link_label = item["Label"]
528
+ end
529
+ link_icon = "Catalog Link Icon"
530
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "cataloglink"})
531
+ end
532
+ end
533
+ end
534
+
535
+ if ebscolinks.count > 0
536
+ ebscolinks.each do |ebscolink|
537
+ if ebscolink["Type"] == "other"
538
+ link_label = "Linked Full Text"
539
+ link_icon = "Linked Full Text Icon"
540
+ if ebscolink.key?("Url")
541
+ link_url = ebscolink["Url"]
542
+ else
543
+ link_url = "detail";
544
+ end
545
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "smartlinks+"})
546
+ end
547
+ end
548
+ end
549
+
550
+ ft_customlinks = @record.fetch('FullText',{}).fetch('CustomLinks',{})
551
+ if ft_customlinks.count > 0
552
+ ft_customlinks.each do |ft_customlink|
553
+ link_url = ft_customlink["Url"]
554
+ link_label = ft_customlink["Text"]
555
+ link_icon = ft_customlink["Icon"]
556
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "customlink-fulltext"})
557
+ end
558
+ end
559
+
560
+ return links
561
+ end
562
+
563
+ def nonfulltext_links
564
+ links = []
565
+ other_customlinks = @record.fetch('CustomLinks',{})
566
+ if other_customlinks.count > 0
567
+ other_customlinks.each do |other_customlink|
568
+ link_url = other_customlink["Url"]
569
+ link_label = other_customlink["Text"]
570
+ link_icon = other_customlink["Icon"]
571
+ links.push({url: link_url, label: link_label, icon: link_icon, type: "customlink-other"})
572
+ end
573
+ end
574
+
575
+ return links
576
+ end
577
+
578
+ def best_fulltext_link
579
+ if self.fulltext_links.count > 0
580
+ return self.fulltext_links[0]
581
+ end
582
+ return {}
583
+ end
584
+
585
+ def retrieve_options
586
+ options = {}
587
+ options['an'] = self.an
588
+ options['dbid'] = self.dbid
589
+ return options
590
+ end
591
+
592
+ end
593
+
594
+ ## SEARCH RESPONSE PARSING
595
+
596
+ class EDSAPIResponse
597
+
598
+ attr_accessor :results, :records, :dblabel, :researchstarters, :publicationmatch, :debug
599
+
600
+ def initialize(search_results)
601
+ @debug = ""
602
+ @results = search_results
603
+
604
+ unless @results['ErrorNumber'].nil?
605
+ return search_results
606
+ end
607
+
608
+ if self.hitcount > 0
609
+ @records = []
610
+ search_results["SearchResult"]["Data"]["Records"].each do |record|
611
+ @records.push(EDSApi::EDSAPIRecord.new(record))
612
+ end
613
+ else
614
+ @records = []
615
+ end
616
+
617
+ @researchstarters = []
618
+ relatedrecords = @results.fetch('SearchResult',{}).fetch('RelatedContent',{}).fetch('RelatedRecords',{})
619
+ if relatedrecords.count > 0
620
+ relatedrecords.each do |related_item|
621
+ if related_item["Type"] == "rs"
622
+ rs_entries = related_item.fetch('Records',{})
623
+ if rs_entries.count > 0
624
+ rs_entries.each do |rs_record|
625
+ @researchstarters.push(EDSApi::EDSAPIRecord.new(rs_record))
626
+ end
627
+ end
628
+ end
629
+ end
630
+ end
631
+
632
+ @publicationmatch = []
633
+ relatedpublications = @results.fetch('SearchResult',{}).fetch('RelatedContent',{}).fetch('RelatedPublications',{})
634
+ if relatedpublications.count > 0
635
+ relatedpublications.each do |related_item|
636
+ if related_item["Type"] == "emp"
637
+ publicationmatches = related_item.fetch('PublicationRecords',{})
638
+ if publicationmatches.count > 0
639
+ publicationmatches.each do |publication_record|
640
+ @publicationmatch.push(EDSApi::EDSAPIRecord.new(publication_record))
641
+ end
642
+ end
643
+ end
644
+ end
645
+ end
646
+ end
647
+
648
+ def hitcount
649
+ @results["SearchResult"]["Statistics"]["TotalHits"]
650
+ end
651
+
652
+ def searchtime
653
+ @results["SearchResult"]["Statistics"]["TotalSearchTime"]
654
+ end
655
+
656
+ def querystring
657
+ @results["SearchRequestGet"]["QueryString"]
658
+ end
659
+
660
+ def current_search
661
+ CGI::parse(self.querystring)
662
+ end
663
+
664
+ def applied_facets
665
+
666
+ af = []
667
+
668
+ applied_facets_section = @results["SearchRequestGet"].fetch('SearchCriteriaWithActions',{}).fetch('FacetFiltersWithAction',{})
669
+ applied_facets_section.each do |applied_facets|
670
+ applied_facets.fetch('FacetValuesWithAction',{}).each do |applied_facet|
671
+ af.push(applied_facet)
672
+ # unless applied_facet['FacetValuesWithAction'].nil?
673
+ # applied_facet_values = applied_facet.fetch('FacetValuesWithAction',{})
674
+ # applied_facet_values.each do |applied_facet_value|
675
+ # af.push(applied_facet_value)
676
+ # end
677
+ # end
678
+ end
679
+ end
680
+
681
+ return af
682
+ end
683
+
684
+ def applied_limiters
685
+
686
+ af = []
687
+
688
+ applied_limters_section = @results["SearchRequestGet"].fetch('SearchCriteriaWithActions',{}).fetch('LimitersWithAction',{})
689
+ applied_limters_section.each do |applied_limter|
690
+ af.push(applied_limter)
691
+ end
692
+
693
+ return af
694
+ end
695
+
696
+ def applied_expanders
697
+
698
+ af = []
699
+
700
+ applied_expanders_section = @results["SearchRequestGet"].fetch('SearchCriteriaWithActions',{}).fetch('ExpandersWithAction',{})
701
+ applied_expanders_section.each do |applied_explander|
702
+ af.push(applied_explander)
703
+ end
704
+
705
+ return af
706
+ end
707
+
708
+ def database_stats
709
+ databases = []
710
+ databases_facet = @results["SearchResult"]["Statistics"]["Databases"]
711
+ databases_facet.each do |database|
712
+ if DB_LABEL_LOOKUP.key?(database["Id"].upcase)
713
+ db_label = DB_LABEL_LOOKUP[database["Id"].upcase];
714
+ else
715
+ db_label = database["Label"]
716
+ end
717
+ databases.push({id: database["Id"], hits: database["Hits"], label: db_label})
718
+ end
719
+ return databases
720
+ end
721
+
722
+ def facets (facet_provided_id = "all")
723
+ facets_hash = []
724
+ available_facets = @results.fetch('SearchResult',{}).fetch('AvailableFacets',{})
725
+ available_facets.each do |available_facet|
726
+ if available_facet["Id"] == facet_provided_id || facet_provided_id == "all"
727
+ facet_label = available_facet["Label"]
728
+ facet_id = available_facet["Id"]
729
+ facet_values = []
730
+ available_facet["AvailableFacetValues"].each do |available_facet_value|
731
+ facet_value = available_facet_value["Value"]
732
+ facet_count = available_facet_value["Count"]
733
+ facet_action = available_facet_value["AddAction"]
734
+ facet_values.push({value: facet_value, hitcount: facet_count, action: facet_action})
735
+ end
736
+ facets_hash.push(id: facet_id, label: facet_label, values: facet_values)
737
+ end
738
+ end
739
+ return facets_hash
740
+ end
741
+
742
+ def date_range
743
+ mindate = @results["SearchResult"]["AvailableCriteria"]["DateRange"]["MinDate"]
744
+ maxdate = @results["SearchResult"]["AvailableCriteria"]["DateRange"]["MaxDate"]
745
+ minyear = mindate[0..3]
746
+ maxyear = maxdate[0..3]
747
+ return {mindate: mindate, maxdate: maxdate, minyear:minyear, maxyear:maxyear}
748
+ end
749
+
750
+ def did_you_mean
751
+ dym_suggestions = @results.fetch('SearchResult', {}).fetch('AutoSuggestedTerms',{})
752
+ dym_suggestions.each do |term|
753
+ return term
754
+ end
755
+ return nil
756
+ end
757
+
758
+ def searchterms
759
+ queries = @results.fetch('SearchRequestGet',{}).fetch('SearchCriteriaWithActions',{}).fetch('QueriesWithAction',{})
760
+
761
+ terms = []
762
+ queries.each do |query|
763
+ query['Query']['Term'].split.each do |word|
764
+ terms.push(word)
765
+ end
766
+ end
767
+
768
+ return terms
769
+ end
770
+
771
+ end
772
+
773
+ class EDSAPIInfo
774
+
775
+ attr_accessor :info
776
+
777
+ def initialize(info_raw)
778
+ @info = info_raw
779
+ end
780
+
781
+ def sorts (id = "all")
782
+ possible_sorts = []
783
+ available_sorts = @info['AvailableSearchCriteria'].fetch('AvailableSorts',{})
784
+ available_sorts.each do |available_sort|
785
+ if available_sort["Id"] == id || id == "all"
786
+ possible_sorts.push(available_sort)
787
+ end
788
+ end
789
+ return possible_sorts
790
+ end
791
+
792
+ def search_fields (id = "all")
793
+ possible_fields = []
794
+ available_fields = @info['AvailableSearchCriteria'].fetch('AvailableSearchFields',{})
795
+ available_fields.each do |available_field|
796
+ if available_field['FieldCode'] == id || id == "all"
797
+ possible_fields.push(available_field)
798
+ end
799
+ end
800
+ return possible_fields
801
+ end
802
+
803
+ def expanders (id = "all")
804
+ possible_expanders = []
805
+ available_expanders = @info['AvailableSearchCriteria'].fetch('AvailableExpanders',{})
806
+ available_expanders.each do |available_expander|
807
+ if available_expander['Id'] == id || id == "all"
808
+ possible_expanders.push(available_expander)
809
+ end
810
+ end
811
+ return possible_expanders
812
+ end
813
+
814
+ def limiters (id = "all")
815
+ possible_limiters = []
816
+ available_limiters = @info['AvailableSearchCriteria'].fetch('AvailableLimiters',{})
817
+ available_limiters.each do |available_limiter|
818
+ if available_limiter['Id'] == id || id == "all"
819
+ possible_limiters.push(available_limiter)
820
+ end
821
+ end
822
+ return possible_limiters
823
+ end
824
+
825
+ def search_modes (id = "all")
826
+ possible_search_modes = []
827
+ available_search_modes = @info['AvailableSearchCriteria'].fetch('AvailableSearchModes',{})
828
+ available_search_modes.each do |available_search_mode|
829
+ if available_search_mode['Mode'] == id || id == "all"
830
+ possible_search_modes.push(available_search_mode)
831
+ end
832
+ end
833
+ return possible_search_modes
834
+ end
835
+
836
+ def related_content (id = "all")
837
+ possible_related_contents = []
838
+ available_related_contents = @info['AvailableSearchCriteria'].fetch('AvailableRelatedContent',{})
839
+ available_related_contents.each do |available_related_content|
840
+ if available_related_content['Type'] == id || id == "all"
841
+ possible_related_contents.push(available_related_content)
842
+ end
843
+ end
844
+ return possible_related_contents
845
+ end
846
+
847
+ def did_you_mean (id = "all")
848
+ possible_dyms = []
849
+ available_dyms = @info['AvailableSearchCriteria'].fetch('AvailableDidYouMeanOptions',{})
850
+ available_dyms.each do |available_dym|
851
+ if available_dym['Id'] == id || id == "all"
852
+ possible_dyms.push(available_dym)
853
+ end
854
+ end
855
+ return possible_dyms
856
+ end
857
+
858
+ def results_per_page
859
+ return @info['ViewResultSettings']['ResultsPerPage']
860
+ end
861
+
862
+ def results_list_view
863
+ return @info['ViewResultSettings']['ResultListView']
864
+ end
865
+
866
+ def default_options
867
+ options = {}
868
+ self.search_modes.each do |search_mode|
869
+ if search_mode['DefaultOn'] == "y"
870
+ options['searchmode'] = [search_mode['Mode']]
871
+ end
872
+ end
873
+
874
+ options['resultsperpage'] = [self.results_per_page]
875
+ options['sort'] = ['relevance']
876
+ options['view'] = [self.results_list_view]
877
+
878
+ default_limiters = []
879
+ self.limiters.each do |limiter|
880
+ if limiter['Type'] == 'select' && limiter['DefaultOn'] == 'y'
881
+ default_limiters.push(limiter['Id']+":"+'y')
882
+ elsif limiter['Type'] == 'multiselectvalue'
883
+ limiter['LimiterValues'].each do |limiter_value|
884
+ unless limiter_value['DefaultOn'].nil?
885
+ default_limiters.push(limiter['Id']+":"+limiter_value['Value'])
886
+ end
887
+ end
888
+ end
889
+ end
890
+ if default_limiters.count > 0
891
+ options['limiter'] = default_limiters
892
+ end
893
+
894
+ default_expanders = []
895
+ self.expanders.each do |expander|
896
+ if expander['DefaultOn'] == 'y'
897
+ default_expanders.push(expander['Id'])
898
+ end
899
+ end
900
+ if default_expanders.count > 0
901
+ options['expander'] = default_expanders
902
+ end
903
+
904
+ default_relatedcontent = []
905
+ self.related_content.each do |related_info|
906
+ if related_info['DefaultOn'] == 'y'
907
+ default_relatedcontent.push(related_info['Type'])
908
+ end
909
+ end
910
+ if default_relatedcontent.count > 0
911
+ options['relatedcontent'] = [default_relatedcontent.join(",")]
912
+ end
913
+
914
+ return options
915
+ end
916
+
917
+ end
918
+
919
+ ## CONNECTION HANDLING
920
+
14
921
  # Connection object. Does what it says. ConnectionHandler is what is usually desired and wraps auto-reonnect features, etc.
15
922
  class Connection
16
923
 
17
924
  attr_accessor :auth_token, :session_token, :guest
18
925
  attr_writer :userid, :password
19
-
926
+
927
+ def initialize
928
+ @log = ""
929
+ end
930
+
20
931
  # Init the object with userid and pass.
21
932
  def uid_init(userid, password, profile, guest = 'y')
22
933
  @userid = userid
@@ -31,7 +942,7 @@ module EDSApi
31
942
  return self
32
943
  end
33
944
  # Auth with the server. Currently only uid auth is supported.
34
-
945
+
35
946
  ###
36
947
  def uid_authenticate(format = :xml)
37
948
  # DO NOT SEND CALL IF YOU HAVE A VALID AUTH TOKEN
@@ -42,7 +953,7 @@ module EDSApi
42
953
  req["Accept"] = "application/json" #if format == :json
43
954
  req.body = xml
44
955
  https = Net::HTTP.new(uri.hostname, uri.port)
45
- https.read_timeout=10
956
+ https.read_timeout=10
46
957
  https.use_ssl = true
47
958
  https.verify_mode = OpenSSL::SSL::VERIFY_NONE
48
959
  begin
@@ -54,11 +965,11 @@ module EDSApi
54
965
  raise "Bad response from server - error code #{result['ErrorNumber']}"
55
966
  else
56
967
  @auth_token = doc['AuthToken']
57
- end
968
+ end
58
969
  end
59
970
  def ip_authenticate(format = :xml)
60
971
  uri = URI "#{API_URL_S}authservice/rest/ipauth"
61
- req = Net::Http:Post.new(uri.request_uri)
972
+ req = Net::HTTP::Post.new(uri.request_uri)
62
973
  req["Accept"] = "application/json" #if format == :json
63
974
  https = Net::HTTP.new(uri.hostname, uri.port)
64
975
  https.read_timeout=10
@@ -82,7 +993,7 @@ module EDSApi
82
993
  # return doc['SessionToken']
83
994
  # }
84
995
  Net::HTTP.start(uri.hostname, uri.port, :read_timeout => 10) { |http|
85
-
996
+
86
997
  begin
87
998
  return http.request(req).body
88
999
  rescue Timeout::Error, Net::ReadTimeout, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
@@ -105,8 +1016,9 @@ module EDSApi
105
1016
  return true
106
1017
  end
107
1018
  # Run a search query, XML results are returned
108
- def search(options, format = :xml)
1019
+ def request_search(options, format = :xml)
109
1020
  uri = URI "#{API_URL}edsapi/rest/Search?#{options}"
1021
+ @log << uri.to_s << " -- "
110
1022
  #return uri.request_uri
111
1023
  req = Net::HTTP::Get.new(uri.request_uri)
112
1024
 
@@ -114,7 +1026,7 @@ module EDSApi
114
1026
  req['x-sessionToken'] = @session_token
115
1027
  req['Accept'] = 'application/json' #if format == :json
116
1028
 
117
- Net::HTTP.start(uri.hostname, uri.port, :read_timeout => 4) { |http|
1029
+ Net::HTTP.start(uri.hostname, uri.port, :read_timeout => 10) { |http|
118
1030
  begin
119
1031
  return http.request(req).body
120
1032
  rescue Timeout::Error, Net::ReadTimeout, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
@@ -123,8 +1035,10 @@ module EDSApi
123
1035
  }
124
1036
  end
125
1037
  # Retrieve specific information
126
- def retrieve(dbid, an, highlightterms = "", ebookpreferredformat = "", format = :xml)
1038
+ def request_retrieve(dbid, an, highlightterms = "", ebookpreferredformat = "", format = :xml)
127
1039
  uri = URI "#{API_URL}edsapi/rest/retrieve?dbid=#{dbid}&an=#{an}"
1040
+ @log << uri.to_s << " -- "
1041
+
128
1042
  if highlightterms != ""
129
1043
  updateURI = uri.to_s
130
1044
  updateURI = updateURI + "&highlightterms=#{highlightterms}"
@@ -149,8 +1063,10 @@ module EDSApi
149
1063
  }
150
1064
  end
151
1065
  # Info method
152
- def info(format = :xml)
1066
+ def request_info(format = :xml)
153
1067
  uri = URI "#{API_URL}edsapi/rest/Info"
1068
+ @log << uri.to_s << " -- "
1069
+
154
1070
  req = Net::HTTP::Get.new(uri.request_uri)
155
1071
  req['x-authenticationToken'] = @auth_token
156
1072
  req['x-sessionToken'] = @session_token
@@ -163,32 +1079,79 @@ module EDSApi
163
1079
  end
164
1080
  }
165
1081
  end
1082
+
1083
+ def show_log
1084
+ return @log
1085
+ end
166
1086
  end
1087
+
167
1088
  # Handles connections - retries failed connections, passes commands along
168
1089
  class ConnectionHandler < Connection
1090
+
169
1091
  attr_accessor :max_retries
170
1092
  attr_accessor :session_token
1093
+ attr_accessor :info
1094
+ attr_accessor :search_results
1095
+
171
1096
  def initialize(max_retries = 2)
172
1097
  @max_retries = max_retries
1098
+ super()
173
1099
  end
1100
+
174
1101
  def show_session_token
175
1102
  return @session_token
176
1103
  end
1104
+
177
1105
  def show_auth_token
178
1106
  return @auth_token
179
1107
  end
1108
+
180
1109
  def create_session(auth_token = @auth_token, format = :xml)
181
1110
  @auth_token = auth_token
182
- result = JSON.parse(super())
183
- if result.has_key?('ErrorNumber')
1111
+ result = JSON.parse(super())
1112
+ if result.has_key?('ErrorNumber')
184
1113
  return result.to_s
185
- else
1114
+ else
186
1115
  @session_token = result['SessionToken']
187
- return result['SessionToken']
188
- end
1116
+ @info = EDSApi::EDSAPIInfo.new(self.request_info(@session_token,@auth_token))
1117
+ return result['SessionToken']
1118
+ end
1119
+ end
1120
+
1121
+ def new_search(searchterm, use_defaults = "y")
1122
+ options = @info.default_options
1123
+ options['query'] = searchterm
1124
+ return self.search(options)
1125
+ end
1126
+
1127
+ def search(options, actions = [])
1128
+ if actions.kind_of?(Array) && actions.count > 0
1129
+ options['action'] = actions
1130
+ elsif actions.length > 0
1131
+ options['action'] = [actions]
1132
+ end
1133
+ apiresponse = EDSApi::EDSAPIResponse.new(request_search(URI.encode_www_form(options)))
1134
+ @current_searchterms = apiresponse.searchterms
1135
+ @search_results = apiresponse
1136
+ return apiresponse
189
1137
  end
190
- def search(options, session_token, auth_token, format = :xml)
191
-
1138
+
1139
+ def search_actions(actions)
1140
+ return self.search(@search_results.current_search,actions)
1141
+ end
1142
+
1143
+ def retrieve(options)
1144
+ options['highlightterms'] = @current_searchterms
1145
+ options['ebookpreferredformat'] = 'ebook-epub'
1146
+ apiresponse = request_retrieve(options['dbid'],options['an'],options['hhighlightterms'])
1147
+ unless apiresponse["Record"].nil?
1148
+ return EDSApi::EDSAPIRecord.new(apiresponse["Record"])
1149
+ end
1150
+ return apiresponse
1151
+ end
1152
+
1153
+ def request_search(options, session_token = @session_token, auth_token = @auth_token, format = :xml)
1154
+
192
1155
  # temporary fix while API SI resolves
193
1156
  # catches case where user navigates past result page 250 and applies facet/limiter
194
1157
  if (options.index('&action=') && (options.index('&action=') > 0))
@@ -203,7 +1166,7 @@ module EDSApi
203
1166
  end
204
1167
  end
205
1168
  end
206
-
1169
+
207
1170
  attempts = 0
208
1171
  @session_token = session_token
209
1172
  @auth_token = auth_token
@@ -224,7 +1187,7 @@ module EDSApi
224
1187
  self.uid_authenticate(:json)
225
1188
  result = JSON.parse(super(options, format))
226
1189
  else
227
- return result
1190
+ return result
228
1191
  end
229
1192
  unless result.has_key?('ErrorNumber')
230
1193
  return result
@@ -238,10 +1201,11 @@ module EDSApi
238
1201
  end
239
1202
  end
240
1203
  end
241
- def info (session_token, auth_token, format= :xml)
242
- attempts = 0
243
- @auth_token = auth_token
244
- @session_token = session_token
1204
+
1205
+ def request_info (session_token, auth_token, format= :xml)
1206
+ attempts = 0
1207
+ @auth_token = auth_token
1208
+ @session_token = session_token
245
1209
  loop do
246
1210
  result = JSON.parse(super(format)) # JSON Parse
247
1211
  if result.has_key?('ErrorNumber')
@@ -262,9 +1226,10 @@ module EDSApi
262
1226
  else
263
1227
  return result
264
1228
  end
265
- end
266
- end
267
- def retrieve(dbid, an, highlightterms, ebookpreferredformat, session_token, auth_token, format = :xml)
1229
+ end
1230
+ end
1231
+
1232
+ def request_retrieve(dbid, an, highlightterms, ebookpreferredformat = 'ebook-epub', session_token = @session_token, auth_token = @auth_token, format = :xml)
268
1233
  attempts = 0
269
1234
  @session_token = session_token
270
1235
  @auth_token = auth_token
@@ -312,4 +1277,4 @@ end
312
1277
  if __FILE__ == $0
313
1278
  benchmark(true)
314
1279
  benchmark
315
- end
1280
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ebsco-discovery-service-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.10
4
+ version: 1.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Frierson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-10 00:00:00.000000000 Z
11
+ date: 2017-03-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Set of Ruby functions to interface with the EBSCO Discovery Service API.
14
14
  email: eds@ebscohost.com
@@ -36,7 +36,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
36
36
  version: '0'
37
37
  requirements: []
38
38
  rubyforge_project:
39
- rubygems_version: 2.2.2
39
+ rubygems_version: 2.6.6
40
40
  signing_key:
41
41
  specification_version: 4
42
42
  summary: EBSCO Discovery Service API Ruby Library