ebsco-discovery-service-api 1.1.10 → 1.1.12

Sign up to get free protection for your applications and to get access to all the features.
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