ebsco-eds 0.0.1.pre

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.
@@ -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
+