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