ebsco-eds 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ require 'json'
2
+
3
+ module JSONable
4
+ module ClassMethods
5
+ attr_accessor :attributes
6
+
7
+ def attr_accessor(*attrs)
8
+ self.attributes = Array attrs
9
+ super
10
+ end
11
+ end
12
+
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ def as_json
18
+ serialized = Hash.new
19
+ self.class.attributes.each do |attribute|
20
+ serialized[attribute] = self.public_send attribute
21
+ end
22
+ serialized
23
+ end
24
+
25
+ def to_json(*a)
26
+ as_json.to_json(*a)
27
+ end
28
+ end
@@ -0,0 +1,339 @@
1
+ require 'ebsco/eds/jsonable'
2
+
3
+ module EBSCO
4
+
5
+ module EDS
6
+
7
+ class Options
8
+ include JSONable
9
+ attr_accessor :SearchCriteria, :RetrievalCriteria, :Actions
10
+ def initialize(options = {}, info)
11
+
12
+ @SearchCriteria = EBSCO::EDS::SearchCriteria.new(options, info)
13
+
14
+ @RetrievalCriteria = EBSCO::EDS::RetrievalCriteria.new(options, info)
15
+
16
+ @Actions = []
17
+
18
+ options.each do |key, value|
19
+
20
+ case key
21
+
22
+ when :actions
23
+ add_actions(options[:actions], info)
24
+
25
+ # solr facet translation
26
+ # "f"=>{"format"=>["eBooks"]}
27
+ when 'f'
28
+ if value.has_key?('format')
29
+ format_list = value['format']
30
+ format_list.each do |item|
31
+ @Actions.push "addfacetfilter(SourceType:#{item})"
32
+ end
33
+ end
34
+ if value.has_key?('language_facet')
35
+ lang_list = value['language_facet']
36
+ lang_list.each do |item|
37
+ @Actions.push "addfacetfilter(Language:#{item})"
38
+ end
39
+ end
40
+ if value.has_key?('subject_topic_facet')
41
+ subj_list = value['subject_topic_facet']
42
+ subj_list.each do |item|
43
+ @Actions.push "addfacetfilter(SubjectEDS:#{item})"
44
+ end
45
+ end
46
+
47
+ puts 'ACTIONS: ' + @Actions.inspect
48
+
49
+ else
50
+
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ def add_actions(actions, info)
57
+ if actions.kind_of?(Array) && actions.count > 0
58
+ actions.each do |item|
59
+ #if is_valid_action(item, info)
60
+ @Actions.push item
61
+ #end
62
+ end
63
+ else
64
+ #if is_valid_action(actions, info)
65
+ @Actions = [actions]
66
+ #else
67
+ #end
68
+ end
69
+ end
70
+
71
+ # def is_valid_action(action, info)
72
+ # # actions in info that require an enumerated value (e.g., addlimiter(LA99:Bulgarian))
73
+ # _available_actions = info.available_actions
74
+ # _defined_action = _available_actions.include? action
75
+ # # actions not enumerated in info (e.g., GoToPage(3))
76
+ # _available_standard_actions = ['GoToPage']
77
+ # _standard_action = _available_standard_actions.any? { |std| action.include? std }
78
+ # # actions in info that require a user supplied value (e.g., addlimiter(TI:value))
79
+ # _available_value_actions = %w{PG4 CS1 FM FT FR RV DT1 SO}
80
+ # _value_action = _available_value_actions.any? { |type| action.include? type }
81
+ #
82
+ # if _value_action || _defined_action || _standard_action
83
+ # true
84
+ # else
85
+ # false
86
+ # end
87
+ # end
88
+
89
+ end
90
+
91
+ class SearchCriteria
92
+ include JSONable
93
+ attr_accessor :Queries, :SearchMode, :IncludeFacets, :FacetFilters, :Limiters, :Sort, :PublicationId,
94
+ :RelatedContent, :AutoSuggest, :Expanders
95
+
96
+ def initialize(options = {}, info)
97
+
98
+ # defaults
99
+ @SearchMode = info.default_search_mode
100
+ @IncludeFacets = 'y'
101
+ @Sort = 'relevance'
102
+ @AutoSuggest = info.default_auto_suggest
103
+ _has_query = false
104
+
105
+ @Expanders = info.default_expander_ids
106
+ _my_expanders = []
107
+ _available_expander_ids = info.available_expander_ids
108
+
109
+ @Limiter = nil
110
+ _my_limiters = []
111
+
112
+ @RelatedContent = info.default_related_content_types
113
+ _my_related_content = []
114
+ _available_related_content_types = info.available_related_content_types
115
+
116
+ options.each do |key, value|
117
+
118
+ case key
119
+
120
+ # ====================================================================================
121
+ # query
122
+ # ====================================================================================
123
+ when :query, 'q'
124
+
125
+ # add blacklight search_fields
126
+ _field_code = ''
127
+ if options.has_key? 'search_field'
128
+ _field = options['search_field']
129
+ case _field
130
+ when 'author'
131
+ _field_code = 'AU'
132
+ when 'subject'
133
+ _field_code = 'SU'
134
+ when 'title'
135
+ _field_code = 'TI'
136
+ end
137
+ end
138
+
139
+ if not _field_code == ''
140
+ @Queries = [{:FieldCode => _field_code, :Term => value}]
141
+ else
142
+ @Queries = [{:Term => value}]
143
+ end
144
+ _has_query = true
145
+
146
+ # ====================================================================================
147
+ # mode
148
+ # ====================================================================================
149
+ when :mode
150
+ if info.available_search_mode_types.include? value.downcase
151
+ @SearchMode = value.downcase
152
+ else
153
+ @SearchMode = info.default_search_mode
154
+ end
155
+
156
+ # ====================================================================================
157
+ # facets
158
+ # ====================================================================================
159
+ when :include_facets
160
+ @IncludeFacets = value ? 'y' : 'n'
161
+
162
+ when :facet_filters
163
+ @FacetFilters = value
164
+
165
+ # ====================================================================================
166
+ # sort
167
+ # ====================================================================================
168
+ when :sort, 'sort'
169
+ if info.available_sorts(value.downcase).empty?
170
+ if value.downcase == 'newest' || value.downcase == 'pub_date_sort desc'
171
+ @Sort = 'date'
172
+ elsif value.downcase == 'oldest' || value.downcase == 'pub_date_sort asc'
173
+ @Sort = 'date2'
174
+ elsif value.downcase == 'score desc'
175
+ @Sort = 'relevance'
176
+ else
177
+ @Sort = 'relevance'
178
+ end
179
+ else
180
+ @Sort = value.downcase
181
+ end
182
+
183
+ # ====================================================================================
184
+ # publication id
185
+ # ====================================================================================
186
+ when :publication_id
187
+ @PublicationId = value
188
+
189
+ when :auto_suggest
190
+ @AutoSuggest = value ? 'y' : 'n'
191
+
192
+ # ====================================================================================
193
+ # expanders
194
+ # ====================================================================================
195
+ when :expanders
196
+ value.each do |item|
197
+ if _available_expander_ids.include? item.downcase
198
+ _my_expanders.push(item)
199
+ end
200
+ end
201
+ if _my_expanders.empty?
202
+ _my_expanders = info.default_expander_ids
203
+ end
204
+ @Expanders = _my_expanders
205
+
206
+ # ====================================================================================
207
+ # limiters
208
+ # ====================================================================================
209
+ when :limiters
210
+ value.each do |item|
211
+ _key = item.split(':',2).first.upcase
212
+ _values = item.split(':',2).last
213
+ # is limiter id available?
214
+ if info.available_limiter_ids.include? _key
215
+ _limiter = info.available_limiters(_key)
216
+ # if multi-value, add the values if they're available
217
+ if _limiter['Type'] == 'multiselectvalue'
218
+ _available_values = info.available_limiter_values(_key)
219
+ _multi_values = []
220
+ _values.split(',').each do |val|
221
+ # todo: make case insensitive?
222
+ if _available_values.include? val
223
+ _multi_values.push(val)
224
+ end
225
+ end
226
+ if _multi_values.empty?
227
+ # do nothing, none of the values are available
228
+ else
229
+ _my_limiters.push({:Id => _key, :Values => _multi_values})
230
+ end
231
+ # single value, just pass it on
232
+ else
233
+ _my_limiters.push({:Id => _key, :Values => [_values]})
234
+ end
235
+ end
236
+ end
237
+ @Limiters = _my_limiters
238
+
239
+ # ====================================================================================
240
+ # related content
241
+ # ====================================================================================
242
+ when :related_content
243
+ value.each do |item|
244
+ if _available_related_content_types.include? item.downcase
245
+ _available_related_content_types.push(item)
246
+ else
247
+ # silently ignore
248
+ end
249
+ end
250
+ if _my_related_content.empty?
251
+ _my_related_content = info.default_related_content_types
252
+ end
253
+ @RelatedContent = _my_related_content
254
+
255
+ # ====================================================================================
256
+ # unsupported parameters, ignore
257
+ # ====================================================================================
258
+ else
259
+ # ignore
260
+
261
+ end
262
+
263
+
264
+ end
265
+
266
+ end
267
+ end
268
+
269
+ class RetrievalCriteria
270
+ include JSONable
271
+ attr_accessor :View, :ResultsPerPage, :PageNumber, :Highlight
272
+ def initialize(options = {}, info)
273
+
274
+ # defaults
275
+ @View = info.default_result_list_view
276
+ @ResultsPerPage = info.default_results_per_page
277
+ @PageNumber = 1
278
+
279
+ options.each do |key, value|
280
+
281
+ case key
282
+
283
+ # ====================================================================================
284
+ # view
285
+ # ====================================================================================
286
+ when :view
287
+ if info.available_result_list_views.include? value.downcase
288
+ @View = value.downcase
289
+ else
290
+ @View = info.default_result_list_view
291
+ end
292
+
293
+ # ====================================================================================
294
+ # results per page
295
+ # ====================================================================================
296
+ when :results_per_page, 'rows', 'per_page'
297
+ if value.to_i > info.max_results_per_page
298
+ @ResultsPerPage = info.max_results_per_page
299
+ else
300
+ @ResultsPerPage = value.to_i
301
+ end
302
+
303
+ # ====================================================================================
304
+ # page number
305
+ # ====================================================================================
306
+ when :page_number, 'page'
307
+ @PageNumber = value.to_i
308
+ # puts 'NEW PAGE: ' + @PageNumber.inspect
309
+ # solr starts at page 0
310
+ when 'start'
311
+ @PageNumber = value.to_i + 1
312
+
313
+ # ====================================================================================
314
+ # highlight
315
+ # ====================================================================================
316
+ when :highlight
317
+ @Highlight = value ? 'y' : 'n'
318
+ # solr/blacklight version
319
+ when 'hl'
320
+ if value == 'on'
321
+ @Highlight = 'y'
322
+ else
323
+ @Highlight = 'n'
324
+ end
325
+
326
+
327
+ else
328
+
329
+ end
330
+
331
+ end
332
+
333
+
334
+ end
335
+
336
+ end
337
+
338
+ end
339
+ end
@@ -0,0 +1,700 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'bibtex'
4
+
5
+ module EBSCO
6
+
7
+ module EDS
8
+
9
+ # A single search result
10
+ class Record
11
+
12
+ # Raw record as returned by the \EDS API via search or retrieve
13
+ attr_reader :record
14
+
15
+ # Lookup table of databases that have their labels suppressed in the response.
16
+ DBS = YAML::load_file(File.join(__dir__, 'settings.yml'))['databases']
17
+
18
+ # Creates a search or retrieval result record
19
+ def initialize(results_record)
20
+
21
+ if results_record.key? 'Record'
22
+ @record = results_record['Record'] # single record returned by retrieve api
23
+ else
24
+ @record = results_record # set of records returned by search api
25
+ end
26
+
27
+ @items = @record.fetch('Items', {})
28
+
29
+ @bib_entity = @record.fetch('RecordInfo', {})
30
+ .fetch('BibRecord', {})
31
+ .fetch('BibEntity', {})
32
+
33
+ @bib_relationships = @record.fetch('RecordInfo', {})
34
+ .fetch('BibRecord', {})
35
+ .fetch('BibRelationships', {})
36
+
37
+ @bib_part = @record.fetch('RecordInfo', {})
38
+ .fetch('BibRecord', {})
39
+ .fetch('BibRelationships', {})
40
+ .fetch('IsPartOfRelationships', {})[0]
41
+
42
+ @bibtex = BibTeX::Entry.new
43
+ end
44
+
45
+ # \Options hash containing accession number and database ID. This can be passed to the retrieve method.
46
+ def retrieve_options
47
+ options = {}
48
+ options['an'] = self.accession_number
49
+ options['dbid'] = self.database_id
50
+ options
51
+ end
52
+
53
+ # The accession number.
54
+ def accession_number
55
+ header_an
56
+ end
57
+
58
+ # The database ID.
59
+ def database_id
60
+ header_db_id
61
+ end
62
+
63
+ # The database name or label.
64
+ def database_name
65
+ header_db_label
66
+ end
67
+
68
+ # The access level.
69
+ def access_level
70
+ header_access_level
71
+ end
72
+
73
+ # The search relevancy score.
74
+ def relevancy_score
75
+ header_score
76
+ end
77
+
78
+ # The title.
79
+ def title
80
+ get_item_data_by_name('Title') || bib_title
81
+ end
82
+
83
+ # The source title (e.g., Journal)
84
+ def source_title
85
+ bib_source_title || get_item_data_by_name('TitleSource')
86
+ end
87
+
88
+ # Other alternative titles.
89
+ def other_titles
90
+ get_item_data_by_name('TitleAlt')
91
+ end
92
+
93
+ # The abstract
94
+ def abstract
95
+ get_item_data_by_name('Abstract')
96
+ end
97
+
98
+ # The list of authors
99
+ def authors
100
+ bib_authors || get_item_data_by_name('Author')
101
+ end
102
+
103
+ # The author affiliations
104
+ def author_affiliations
105
+ get_item_data_by_name('AffiliationAuthor')
106
+ end
107
+
108
+ # The list of subject terms.
109
+ def subjects
110
+ bib_subjects || get_item_data_by_name('Subject')
111
+ end
112
+
113
+ # The list of geographic subjects
114
+ def subjects_geographic
115
+ get_item_data_by_name('SubjectGeographic')
116
+ end
117
+
118
+ # The list of person subjects
119
+ def subjects_person
120
+ get_item_data_by_name('SubjectPerson')
121
+ end
122
+
123
+ # Author supplied keywords
124
+ def author_supplied_keywords
125
+ get_item_data_by_label('Author-Supplied Keywords')
126
+ end
127
+
128
+ # Notes
129
+ def notes
130
+ get_item_data_by_name('Note')
131
+ end
132
+
133
+ # Languages
134
+ def languages
135
+ get_item_data_by_name('Language') || bib_languages
136
+ end
137
+
138
+ # Total number of pages.
139
+ def page_count
140
+ bib_page_count
141
+ end
142
+
143
+ # Starting page number.
144
+ def page_start
145
+ bib_page_start
146
+ end
147
+
148
+ # Physical description.
149
+ def physical_description
150
+ get_item_data_by_name('PhysDesc')
151
+ end
152
+
153
+ # Publication type.
154
+ def publication_type
155
+ header_publication_type || get_item_data_by_name('TypePub')
156
+ end
157
+
158
+ # Publication type ID.
159
+ def publication_type_id
160
+ header_publication_type_id
161
+ end
162
+
163
+ # Publication date.
164
+ def publication_date
165
+ bib_publication_date || get_item_data_by_name('DatePub')
166
+ end
167
+
168
+ # Publication year.
169
+ def publication_year
170
+ bib_publication_year || get_item_data_by_name('DatePub')
171
+ end
172
+
173
+ # Publisher information.
174
+ def publisher_info
175
+ get_item_data_by_label('Publication Information')
176
+ end
177
+
178
+ # Document type.
179
+ def document_type
180
+ get_item_data_by_name('TypeDocument')
181
+ end
182
+
183
+ # DOI identifier.
184
+ def doi
185
+ get_item_data_by_name('DOI') || bib_doi
186
+ end
187
+
188
+ # OCLC identifier.
189
+ def oclc
190
+ get_item_data_by_label('OCLC')
191
+ end
192
+
193
+ # Prind ISSN
194
+ def issn_print
195
+ get_item_data_by_name('ISSN') || bib_issn_print
196
+ end
197
+
198
+ # List of ISSNs
199
+ def issns
200
+ bib_issns
201
+ end
202
+
203
+ # List of ISBNs
204
+ def isbns
205
+ bib_isbns | item_related_isbns
206
+ end
207
+
208
+ # Print ISBN
209
+ def isbn_print
210
+ bib_isbn_print
211
+ end
212
+
213
+ # Electronic ISBN
214
+ def isbn_electronic
215
+ bib_isbn_electronic
216
+ end
217
+
218
+ # Series information.
219
+ def series
220
+ get_item_data_by_name('SeriesInfo')
221
+ end
222
+
223
+ # Volume
224
+ def volume
225
+ bib_volume
226
+ end
227
+
228
+ # Issue
229
+ def issue
230
+ bib_issue
231
+ end
232
+
233
+ # Cover images
234
+ def covers
235
+ images
236
+ end
237
+
238
+ # Cover image - thumbnail size link
239
+ def cover_thumb_url
240
+ images('thumb').first[:src]
241
+ end
242
+
243
+ # Cover image - medium size link
244
+ def cover_medium_url
245
+ images('medium').first[:src]
246
+ end
247
+
248
+ # Word count for fulltext.
249
+ def fulltext_word_count
250
+ get_item_data_by_name('FullTextWordCount').to_i
251
+ end
252
+
253
+ # --
254
+ # ====================================================================================
255
+ # GENERAL: ResultId, PLink, ImageInfo, CustomLinks, FullText
256
+ # ====================================================================================
257
+ # ++
258
+
259
+ # Result ID.
260
+ def result_id
261
+ @record['ResultId']
262
+ end
263
+
264
+ # EBSCO's persistent link.
265
+ def plink
266
+ @record['PLink']
267
+ end
268
+
269
+ # Fulltext.
270
+ def html_fulltext
271
+ if @record.fetch('FullText',{}).fetch('Text',{}).fetch('Availability',0) == '1'
272
+ @record.fetch('FullText',{}).fetch('Text',{})['Value']
273
+ else
274
+ nil
275
+ end
276
+ end
277
+
278
+ # List of cover images.
279
+ def images (size_requested = 'all')
280
+ returned_images = []
281
+ images = @record.fetch('ImageInfo', {})
282
+ if images.count > 0
283
+ images.each do |image|
284
+ if size_requested == image['Size'] || size_requested == 'all'
285
+ returned_images.push({size: image['Size'], src: image['Target']})
286
+ end
287
+ end
288
+ end
289
+ returned_images
290
+ end
291
+
292
+ # --
293
+ # ====================================================================================
294
+ # LINK HELPERS
295
+ # ====================================================================================
296
+ # ++
297
+
298
+ # A list of all available links.
299
+ def all_links
300
+ self.fulltext_links + self.non_fulltext_links
301
+ end
302
+
303
+ # The first fulltext link.
304
+ def fulltext_link
305
+ self.fulltext_links.first || {}
306
+ end
307
+
308
+ # All available fulltext links.
309
+ def fulltext_links
310
+
311
+ links = []
312
+
313
+ ebscolinks = @record.fetch('FullText',{}).fetch('Links',{})
314
+ if ebscolinks.count > 0
315
+ ebscolinks.each do |ebscolink|
316
+ if ebscolink['Type'] == 'pdflink'
317
+ link_label = 'PDF Full Text'
318
+ link_icon = 'PDF Full Text Icon'
319
+ link_url = ebscolink['Url'] || 'detail'
320
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'pdf'})
321
+ end
322
+ end
323
+ end
324
+
325
+ htmlfulltextcheck = @record.fetch('FullText',{}).fetch('Text',{}).fetch('Availability',{})
326
+ if htmlfulltextcheck == '1'
327
+ link_url = 'detail'
328
+ link_label = 'Full Text in Browser'
329
+ link_icon = 'Full Text in Browser Icon'
330
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'html'})
331
+ end
332
+
333
+ if ebscolinks.count > 0
334
+ ebscolinks.each do |ebscolink|
335
+ if ebscolink['Type'] == 'ebook-pdf'
336
+ link_label = 'PDF eBook Full Text'
337
+ link_icon = 'PDF eBook Full Text Icon'
338
+ link_url = ebscolink['Url'] || 'detail'
339
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'ebook-pdf'})
340
+ end
341
+ end
342
+ end
343
+
344
+ if ebscolinks.count > 0
345
+ ebscolinks.each do |ebscolink|
346
+ if ebscolink['Type'] == 'ebook-epub'
347
+ link_label = 'ePub eBook Full Text'
348
+ link_icon = 'ePub eBook Full Text Icon'
349
+ link_url = ebscolink['Url'] || 'detail'
350
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'ebook-epub'})
351
+ end
352
+ end
353
+ end
354
+
355
+ items = @record.fetch('Items',{})
356
+ if items.count > 0
357
+ items.each do |item|
358
+ if item['Group'] == 'Url'
359
+ if item['Data'].include? 'linkTerm="'
360
+ link_start = item['Data'].index('linkTerm="')+15
361
+ link_url = item['Data'][link_start..-1]
362
+ link_end = link_url.index('"')-1
363
+ link_url = link_url[0..link_end]
364
+ link_label_start = item['Data'].index('link>')+8
365
+ link_label = item['Data'][link_label_start..-1]
366
+ link_label = link_label.strip
367
+ else
368
+ link_url = item['Data']
369
+ link_label = item['Label']
370
+ end
371
+ link_icon = 'Catalog Link Icon'
372
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'cataloglink'})
373
+ end
374
+ end
375
+ end
376
+
377
+ if ebscolinks.count > 0
378
+ ebscolinks.each do |ebscolink|
379
+ if ebscolink['Type'] == 'other'
380
+ link_label = 'Linked Full Text'
381
+ link_icon = 'Linked Full Text Icon'
382
+ link_url = ebscolink['Url'] || 'detail'
383
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'smartlinks+'})
384
+ end
385
+ end
386
+ end
387
+
388
+ ft_customlinks = @record.fetch('FullText',{}).fetch('CustomLinks',{})
389
+ if ft_customlinks.count > 0
390
+ ft_customlinks.each do |ft_customlink|
391
+ link_url = ft_customlink['Url']
392
+ link_label = ft_customlink['Text']
393
+ link_icon = ft_customlink['Icon']
394
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'customlink-fulltext'})
395
+ end
396
+ end
397
+
398
+ links
399
+ end
400
+
401
+ # All available non-fulltext links.
402
+ def non_fulltext_links
403
+ links = []
404
+ other_customlinks = @record.fetch('CustomLinks',{})
405
+ if other_customlinks.count > 0
406
+ other_customlinks.each do |other_customlink|
407
+ link_url = other_customlink['Url']
408
+ link_label = other_customlink['Text']
409
+ link_icon = other_customlink['Icon']
410
+ links.push({url: link_url, label: link_label, icon: link_icon, type: 'customlink-other'})
411
+ end
412
+ end
413
+
414
+ links
415
+ end
416
+
417
+ #:nodoc: all
418
+ # No need to document methods below
419
+
420
+ # Experimental bibtex support.
421
+ def retrieve_bibtex
422
+
423
+ @bibtex.key = self.accession_number
424
+ @bibtex.title = self.title
425
+ if self.bib_authors_list.length > 0
426
+ @bibtex.author = self.bib_authors_list.join(' and ').chomp
427
+ end
428
+ @bibtex.year = self.publication_year.to_i
429
+
430
+ # bibtex type
431
+ _type = self.publication_type
432
+ case _type
433
+ when 'Academic Journal'
434
+ @bibtex.type = :article
435
+ @bibtex.journal = self.source_title
436
+ if self.issue
437
+ @bibtex.issue = self.issue
438
+ end
439
+ if self.volume
440
+ @bibtex.number = self.volume
441
+ end
442
+ if self.page_start && self.page_count
443
+ @bibtex.pages = self.page_start + '-' + (self.page_start.to_i + self.page_count.to_i-1).to_s
444
+ end
445
+ if self.bib_publication_month
446
+ @bibtex.month = self.bib_publication_month.to_i
447
+ end
448
+ when 'Conference'
449
+ @bibtex.type = :conference
450
+ @bibtex.booktitle = self.source_title
451
+ if self.issue
452
+ @bibtex.issue = self.issue
453
+ end
454
+ if self.volume
455
+ @bibtex.number = self.volume
456
+ end
457
+ if self.page_start && self.page_count
458
+ @bibtex.pages = self.page_start + '-' + (self.page_start.to_i + self.page_count.to_i-1).to_s
459
+ end
460
+ if self.bib_publication_month
461
+ @bibtex.month = self.bib_publication_month.to_i
462
+ end
463
+ if self.publisher_info
464
+ @bibtex.publisher = self.publisher_info
465
+ end
466
+ if self.series
467
+ @bibtex.series = self.series
468
+ end
469
+ when 'Book', 'eBook'
470
+ @bibtex.type = :book
471
+ if self.publisher_info
472
+ @bibtex.publisher = self.publisher_info
473
+ end
474
+ if self.series
475
+ @bibtex.series = self.series
476
+ end
477
+ if self.bib_publication_month
478
+ @bibtex.month = self.bib_publication_month.to_i
479
+ end
480
+ if self.isbns
481
+ @bibtex.isbn = self.isbns.first
482
+ end
483
+ else
484
+ @bibtex.type = :other
485
+ end
486
+ @bibtex
487
+ end
488
+
489
+ # ====================================================================================
490
+ # HEADER: DbId, DbLabel, An, PubType, PubTypeId, AccessLevel
491
+ # ====================================================================================
492
+
493
+ def header_an
494
+ @record['Header']['An'].to_s
495
+ end
496
+
497
+ def header_db_id
498
+ @record['Header']['DbId'].to_s
499
+ end
500
+
501
+ # only available from search not retrieve
502
+ def header_score
503
+ @record['Header']['RelevancyScore']
504
+ end
505
+
506
+ def header_publication_type
507
+ @record['Header']['PubType']
508
+ end
509
+
510
+ def header_publication_type_id
511
+ @record['Header']['PubTypeId']
512
+ end
513
+
514
+ def header_db_label
515
+ DBS[self.database_id.upcase] || @record['Header']['DbLabel']
516
+ end
517
+
518
+ # not sure the rules for when this appears or not - RecordInfo.AccessInfo?
519
+ def header_access_level
520
+ @record['Header']['AccessLevel']
521
+ end
522
+
523
+ # ====================================================================================
524
+ # ITEMS
525
+ # ====================================================================================
526
+
527
+ # look up by 'Name' and return 'Data'
528
+ def get_item_data_by_name(name)
529
+ _item_property = @items.find{|item| item['Name'] == name}
530
+ if _item_property.nil?
531
+ nil
532
+ else
533
+ _item_property['Data']
534
+ end
535
+ end
536
+
537
+ # look up by 'Label' and return 'Data'
538
+ def get_item_data_by_label(label)
539
+ _item_property = @items.find{|item| item['Label'] == label}
540
+ if _item_property.nil?
541
+ nil
542
+ else
543
+ _item_property['Data']
544
+ end
545
+ end
546
+
547
+ def item_related_isbns
548
+ get_item_data_by_label('Related ISBNs').split(' ').map!{|item| item.gsub(/\.$/, '')}
549
+ end
550
+
551
+ # ====================================================================================
552
+ # BIB ENTITY
553
+ # ====================================================================================
554
+
555
+ def bib_title
556
+ @bib_entity.fetch('Titles', {}).find{|item| item['Type'] == 'main'}['TitleFull']
557
+ end
558
+
559
+ def bib_authors
560
+ @bib_relationships.deep_find('NameFull').join('; ')
561
+ end
562
+
563
+ def bib_authors_list
564
+ @bib_relationships.deep_find('NameFull')
565
+ end
566
+
567
+ def bib_subjects
568
+ @bib_entity.deep_find('SubjectFull')
569
+ end
570
+
571
+ def bib_languages
572
+ @bib_entity.fetch('Languages', {}).map{|lang| lang['Text']}
573
+ end
574
+
575
+ # def bib_pages
576
+ # @bib_entity.fetch('PhysicalDescription', {})['Pagination']
577
+ # end
578
+
579
+ def bib_page_count
580
+ @bib_entity.deep_find('PageCount').first
581
+ end
582
+
583
+ def bib_page_start
584
+ @bib_entity.deep_find('StartPage').first
585
+ end
586
+
587
+ def bib_doi
588
+ @bib_entity.fetch('Identifiers',{}).find{|item| item['Type'] == 'doi'}['Value']
589
+ end
590
+
591
+ # ====================================================================================
592
+ # BIB - IS PART OF (journal, book)
593
+ # ====================================================================================
594
+
595
+ def bib_source_title
596
+ @bib_part.fetch('BibEntity',{}).fetch('Titles',{}).find{|item| item['Type'] == 'main'}['TitleFull']
597
+ end
598
+
599
+ def bib_issn_print
600
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).find{|item| item['Type'] == 'issn-print'}['Value']
601
+ end
602
+
603
+ def bib_issn_electronic
604
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).find{|item| item['Type'] == 'issn-electronic'}['Value']
605
+ end
606
+
607
+ def bib_issns
608
+ issns = []
609
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).each do |id|
610
+ if id['Type'].include?('issn') && !id['Type'].include?('locals')
611
+ issns.push(id['Value'])
612
+ end
613
+ end
614
+ issns
615
+ end
616
+
617
+ def bib_isbn_print
618
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).find{|item| item['Type'] == 'isbn-print'}['Value']
619
+ end
620
+
621
+ def bib_isbn_electronic
622
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).find{|item| item['Type'] == 'isbn-electronic'}['Value']
623
+ end
624
+
625
+ # todo: make this generic and take an optional parameter for type
626
+ def bib_isbns
627
+ isbns = []
628
+ @bib_part.fetch('BibEntity',{}).fetch('Identifiers',{}).each do |id|
629
+ if id['Type'].include?('isbn') && !id['Type'].include?('locals')
630
+ isbns.push(id['Value'])
631
+ end
632
+ end
633
+ isbns
634
+ end
635
+
636
+ def bib_publication_date
637
+ _date = @bib_part.fetch('BibEntity',{}).fetch('Dates',{}).find{|item| item['Type'] == 'published'}
638
+ if _date
639
+ if _date.has_key?('Y') && _date.has_key?('M') && _date.has_key?('D')
640
+ _date['Y'] + '-' + _date['M'] + '-' + _date['D']
641
+ else
642
+ nil
643
+ end
644
+ else
645
+ nil
646
+ end
647
+ end
648
+
649
+ def bib_publication_year
650
+ _date = @bib_part.fetch('BibEntity',{}).fetch('Dates',{}).find{|item| item['Type'] == 'published'}
651
+ if _date
652
+ _date.has_key?('Y') ? _date['Y'] : nil
653
+ else
654
+ nil
655
+ end
656
+ end
657
+
658
+ def bib_publication_month
659
+ _date = @bib_part.fetch('BibEntity',{}).fetch('Dates',{}).find{|item| item['Type'] == 'published'}
660
+ if _date
661
+ _date.has_key?('M') ? _date['M'] : nil
662
+ else
663
+ nil
664
+ end
665
+ end
666
+
667
+ def bib_volume
668
+ @bib_part.fetch('BibEntity',{}).fetch('Numbering',{}).find{|item| item['Type'] == 'volume'}['Value']
669
+ end
670
+
671
+ def bib_issue
672
+ @bib_part.fetch('BibEntity',{}).fetch('Numbering',{}).find{|item| item['Type'] == 'issue'}['Value']
673
+ end
674
+
675
+ def to_hash
676
+ hash = {}
677
+ hash['id'] = database_id + '-' + accession_number
678
+ hash['title_display'] = title.gsub('<highlight>', '').gsub('</highlight>', '')
679
+ hash['pub_date'] = publication_year
680
+ hash
681
+ end
682
+
683
+ end # Class Record
684
+ end # Module EDS
685
+ end # Module EBSCO
686
+
687
+
688
+ # monkey patches
689
+ class Hash
690
+ def deep_find(key, object=self, found=[])
691
+ if object.respond_to?(:key?) && object.key?(key)
692
+ found << object[key]
693
+ end
694
+ if object.is_a? Enumerable
695
+ found << object.collect { |*a| deep_find(key, a.last) }
696
+ end
697
+ found.flatten.compact
698
+ end
699
+ end
700
+