stanford-mods 2.5.0 → 2.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,13 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # See stanford-mods.gemspec for this gem's dependencies
4
4
  gemspec
5
-
6
- group :test, :development do
7
- gem 'rubocop', require: false
8
- gem 'rubocop-rspec', require: false
9
- gem 'pry-byebug', require: false, platform: [:ruby_20, :ruby_21]
10
- gem 'coveralls', require: false
11
- end
12
-
13
- # Pin to activesupport 4.x for older versions of ruby
14
- gem 'activesupport', '~> 4.2' if RUBY_VERSION < '2.2.2'
@@ -16,12 +16,14 @@ module Stanford
16
16
  # @return [String] the coordinate in WKT/CQL ENVELOPE representation
17
17
  def as_envelope
18
18
  return unless valid?
19
+
19
20
  "ENVELOPE(#{bounds[:min_x]}, #{bounds[:max_x]}, #{bounds[:max_y]}, #{bounds[:min_y]})"
20
21
  end
21
22
 
22
23
  # @return [String] the coordinate in Solr 4.x+ bbox-format representation
23
24
  def as_bbox
24
25
  return unless valid?
26
+
25
27
  "#{bounds[:min_x]} #{bounds[:min_y]} #{bounds[:max_x]} #{bounds[:max_y]}"
26
28
  end
27
29
 
@@ -44,6 +46,7 @@ module Stanford
44
46
  @bounds ||= begin
45
47
  matches = cleaner_coordinate(value).match %r{\A(?<lat>[EW].+-+.+)\s*/\s*(?<lng>[NS].+-+.+)\Z}
46
48
  return {} unless matches
49
+
47
50
  min_x, max_x = matches['lat'].split(/-+/).map { |x| coord_to_decimal(x) }.minmax
48
51
  min_y, max_y = matches['lng'].split(/-+/).map { |y| coord_to_decimal(y) }.minmax
49
52
  { min_x: min_x, min_y: min_y, max_x: max_x, max_y: max_y }
@@ -32,6 +32,7 @@ module Stanford
32
32
  # @return [Boolean] true if the year is between -999 and (current year + 1); false otherwise
33
33
  def self.year_str_valid?(year_str)
34
34
  return false unless year_str && (year_str.match(/^\d{1,4}$/) || year_str.match(/^-\d{1,3}$/))
35
+
35
36
  (-1000 < year_str.to_i) && (year_str.to_i < Date.today.year + 2)
36
37
  end
37
38
 
@@ -39,6 +40,7 @@ module Stanford
39
40
  # @return [Boolean] true if the year is between -9999 and (current year + 1); false otherwise
40
41
  def self.year_int_valid?(year)
41
42
  return false unless year.is_a? Integer
43
+
42
44
  (-1000 < year.to_i) && (year < Date.today.year + 2)
43
45
  end
44
46
 
@@ -59,6 +61,7 @@ module Stanford
59
61
  return display_str_for_bc if orig_date_str.match(BC_REGEX)
60
62
  # decade next in case there are 4 digits, e.g. 1950s
61
63
  return display_str_for_decade if orig_date_str.match(DECADE_4CHAR_REGEXP) || orig_date_str.match(DECADE_S_REGEXP)
64
+
62
65
  result = sortable_year_for_yyyy_or_yy
63
66
  unless result
64
67
  # try removing brackets between digits in case we have 169[5] or [18]91
@@ -81,6 +84,7 @@ module Stanford
81
84
  return if orig_date_str == '0000-00-00' # shpc collection has these useless dates
82
85
  # B.C. first in case there are 4 digits, e.g. 1600 B.C.
83
86
  return sortable_year_int_for_bc if orig_date_str.match(BC_REGEX)
87
+
84
88
  result = sortable_year_for_yyyy_or_yy
85
89
  result ||= sortable_year_for_decade # 19xx or 20xx
86
90
  result ||= sortable_year_for_century
@@ -102,6 +106,7 @@ module Stanford
102
106
  return if orig_date_str == '0000-00-00' # shpc collection has these useless dates
103
107
  # B.C. first in case there are 4 digits, e.g. 1600 B.C.
104
108
  return sortable_year_str_for_bc if orig_date_str.match(BC_REGEX)
109
+
105
110
  result = sortable_year_for_yyyy_or_yy
106
111
  result ||= sortable_year_for_decade # 19xx or 20xx
107
112
  result ||= sortable_year_for_century
@@ -144,6 +149,7 @@ module Stanford
144
149
  # @return [String, nil] 4 digit year (e.g. 1865, 0950) if orig_date_str matches pattern, nil otherwise
145
150
  def sortable_year_for_yy
146
151
  return unless orig_date_str
152
+
147
153
  slash_matches = orig_date_str.match(/\d{1,2}\/\d{1,2}\/\d{2}/)
148
154
  if slash_matches
149
155
  date_obj = Date.strptime(orig_date_str, '%m/%d/%y')
@@ -196,6 +202,7 @@ module Stanford
196
202
  def sortable_year_for_century
197
203
  return unless orig_date_str
198
204
  return if orig_date_str =~ /B\.C\./
205
+
199
206
  century_matches = orig_date_str.match(CENTURY_4CHAR_REGEXP)
200
207
  if century_matches
201
208
  return $1 + '00' if $1.length == 2
@@ -215,6 +222,7 @@ module Stanford
215
222
  def display_str_for_century
216
223
  return unless orig_date_str
217
224
  return if orig_date_str =~ /B\.C\./
225
+
218
226
  century_str_matches = orig_date_str.match(CENTURY_WORD_REGEXP)
219
227
  return century_str_matches.to_s if century_str_matches
220
228
 
@@ -262,6 +270,7 @@ module Stanford
262
270
  # @return [String, nil] String sortable -ddd if orig_date_str matches pattern; nil otherwise
263
271
  def sortable_year_str_for_early_numeric
264
272
  return unless orig_date_str.match(EARLY_NUMERIC)
273
+
265
274
  if orig_date_str =~ /^\-/
266
275
  # negative number becomes x - 1000 for sorting; -005 for -995
267
276
  num = orig_date_str[1..-1].to_i - 1000
@@ -275,6 +284,7 @@ module Stanford
275
284
  # @return [Integer, nil] Integer sortable -ddd if orig_date_str matches pattern; nil otherwise
276
285
  def sortable_year_int_for_early_numeric
277
286
  return orig_date_str.to_i if orig_date_str.match(EARLY_NUMERIC)
287
+
278
288
  orig_date_str.to_i if orig_date_str =~ /^-\d{4}$/
279
289
  end
280
290
 
@@ -290,6 +300,7 @@ module Stanford
290
300
  return '1 B.C.' if orig_date_str == '0'
291
301
  # negative number becomes B.C.
292
302
  return "#{orig_date_str[1..-1].to_i + 1} B.C." if orig_date_str =~ /^\-/
303
+
293
304
  # remove leading 0s from early dates
294
305
  "#{orig_date_str.to_i} A.D."
295
306
  end
@@ -304,6 +315,7 @@ module Stanford
304
315
  # need more in string than only 2 digits
305
316
  return if orig_date_str.match(/^\d\d$/) || orig_date_str.match(/^\D*\d\d\D*$/)
306
317
  return if orig_date_str =~ /\d\s*B.C./ # skip B.C. dates
318
+
307
319
  date_obj = Date.parse(orig_date_str)
308
320
  date_obj.year.to_s
309
321
  rescue ArgumentError
@@ -40,25 +40,28 @@ module Stanford
40
40
  # @return Array<Integer> an array of publication years for the resource
41
41
  def publication_date_for_slider
42
42
  @originInfo_ng_nodeset.map do |origin_info_node|
43
-
44
43
  date_elements = if origin_info_node.as_object.first.key_dates.any?
45
44
  origin_info_node.as_object.first.key_dates.map(&:as_object).map(&:first)
46
45
  else
47
46
  date_field_keys.map do |date_field|
48
47
  next unless origin_info_node.respond_to?(date_field)
48
+
49
49
  date_elements = origin_info_node.send(date_field)
50
50
  date_elements.map(&:as_object).map(&:first) if date_elements.any?
51
- end.first
51
+ end.compact.first
52
52
  end
53
53
 
54
54
  if date_elements.nil? || date_elements.none?
55
55
  []
56
- elsif date_elements.find(&:start?) && date_elements.find(&:end?)
56
+ elsif date_elements.find(&:start?) &&
57
+ date_elements.find(&:start?).as_range &&
58
+ date_elements.find(&:end?) &&
59
+ date_elements.find(&:end?).as_range
57
60
  start_date = date_elements.find(&:start?)
58
61
  end_date = date_elements.find(&:end?)
59
62
 
60
63
  (start_date.as_range.min.year..end_date.as_range.max.year).to_a
61
- elsif date_elements.find(&:start?)
64
+ elsif date_elements.find(&:start?) && date_elements.find(&:start?).as_range
62
65
  start_date = date_elements.find(&:start?)
63
66
 
64
67
  (start_date.as_range.min.year..Time.now.year).to_a
@@ -80,6 +83,7 @@ module Stanford
80
83
  compact_values = values.compact.reject { |v| v.strip.empty? }
81
84
  return compact_values.join(delimiter) if compact_values.length == 1 ||
82
85
  !ends_in_terminating_punctuation?(delimiter)
86
+
83
87
  compact_values.each_with_index.map do |value, i|
84
88
  if (compact_values.length - 1) == i || # last item?
85
89
  ends_in_terminating_punctuation?(value)
@@ -102,6 +106,7 @@ module Stanford
102
106
 
103
107
  def publisher_vals_str(origin_info_node)
104
108
  return if origin_info_node.publisher.text.strip.empty?
109
+
105
110
  publishers = origin_info_node.publisher.reject do |p|
106
111
  p.text.strip.empty?
107
112
  end.map(&:text)
@@ -112,6 +117,7 @@ module Stanford
112
117
 
113
118
  def place_vals_str(origin_info_node)
114
119
  return if origin_info_node.place.text.strip.empty?
120
+
115
121
  places = place_terms(origin_info_node).reject do |p|
116
122
  p.text.strip.empty?
117
123
  end.map(&:text)
@@ -128,6 +134,7 @@ module Stanford
128
134
  def place_terms(origin_info_element)
129
135
  return [] unless origin_info_element.respond_to?(:place) &&
130
136
  origin_info_element.place.respond_to?(:placeTerm)
137
+
131
138
  if unencoded_place_terms?(origin_info_element)
132
139
  origin_info_element.place.placeTerm.select do |term|
133
140
  !term.attributes['type'].respond_to?(:value) ||
@@ -140,6 +147,7 @@ module Stanford
140
147
  term.attributes['authority'].respond_to?(:value) &&
141
148
  term.attributes['authority'].value == 'marccountry' &&
142
149
  MARC_COUNTRIES.include?(term.text.strip)
150
+
143
151
  term = term.clone
144
152
  term.content = MARC_COUNTRIES[term.text.strip]
145
153
  term
@@ -152,12 +160,14 @@ module Stanford
152
160
  def date_str(origin_info_node)
153
161
  date_vals = origin_info_date_vals(origin_info_node)
154
162
  return if date_vals.empty?
163
+
155
164
  date_vals.map(&:strip).join(' ')
156
165
  end
157
166
 
158
167
  def origin_info_date_vals(origin_info_node)
159
168
  date_field_keys.map do |date_field|
160
169
  next unless origin_info_node.respond_to?(date_field)
170
+
161
171
  date_elements = origin_info_node.send(date_field)
162
172
  date_elements_display_vals(date_elements) if date_elements.present?
163
173
  end.compact.flatten
@@ -336,8 +346,8 @@ module Stanford
336
346
  else
337
347
  ng_date_element.content
338
348
  end
339
- rescue
340
- ng_date_element.content
349
+ rescue
350
+ ng_date_element.content
341
351
  end
342
352
  ng_date_element
343
353
  end
@@ -350,8 +360,8 @@ module Stanford
350
360
  else
351
361
  ng_date_element.content
352
362
  end
353
- rescue
354
- ng_date_element.content
363
+ rescue
364
+ ng_date_element.content
355
365
  end
356
366
  ng_date_element
357
367
  end
@@ -374,8 +384,8 @@ module Stanford
374
384
  else
375
385
  my_ng_date_element.content
376
386
  end
377
- rescue
378
- my_ng_date_element.content
387
+ rescue
388
+ my_ng_date_element.content
379
389
  end
380
390
  my_ng_date_element
381
391
  end
@@ -396,8 +406,8 @@ module Stanford
396
406
  else
397
407
  my_ng_date_element.content
398
408
  end
399
- rescue
400
- my_ng_date_element.content
409
+ rescue
410
+ my_ng_date_element.content
401
411
  end
402
412
  my_ng_date_element
403
413
  end
@@ -17,7 +17,7 @@ module Stanford
17
17
  first_wo_role ||= n if n.role.empty?
18
18
  n.role.each { |r|
19
19
  if r.authority.include?('marcrelator') &&
20
- (r.value.include?('Creator') || r.value.include?('Author'))
20
+ r.value.any? { |v| v.match(/creator/i) || v.match?(/author/i) }
21
21
  result ||= n.display_value_w_date
22
22
  end
23
23
  }
@@ -45,6 +45,7 @@ module Stanford
45
45
  result = []
46
46
  mods_ng_xml.personal_name.map do |n|
47
47
  next if n.role.size.zero?
48
+
48
49
  n.role.each { |r|
49
50
  result << n.display_value_w_date unless includes_marc_relator_collector_role?(r)
50
51
  }
@@ -58,6 +59,7 @@ module Stanford
58
59
  result = []
59
60
  mods_ng_xml.personal_name.each do |n|
60
61
  next if n.role.size.zero?
62
+
61
63
  n.role.each { |r|
62
64
  result << n.display_value_w_date if includes_marc_relator_collector_role?(r)
63
65
  }
@@ -82,6 +82,7 @@ module Stanford
82
82
  def year_display_str(date_el_array)
83
83
  result = date_parsing_result(date_el_array, :date_str_for_display)
84
84
  return result if result
85
+
85
86
  _ignore, orig_str_to_parse = self.class.earliest_year_str(date_el_array)
86
87
  DateParsing.date_str_for_display(orig_str_to_parse) if orig_str_to_parse
87
88
  end
@@ -93,6 +94,7 @@ module Stanford
93
94
  def year_int(date_el_array)
94
95
  result = date_parsing_result(date_el_array, :year_int_from_date_str)
95
96
  return result if result
97
+
96
98
  year_int, _ignore = self.class.earliest_year_int(date_el_array)
97
99
  year_int if year_int
98
100
  end
@@ -104,6 +106,7 @@ module Stanford
104
106
  def year_sort_str(date_el_array)
105
107
  result = date_parsing_result(date_el_array, :sortable_year_string_from_date_str)
106
108
  return result if result
109
+
107
110
  sortable_str, _ignore = self.class.earliest_year_str(date_el_array)
108
111
  sortable_str if sortable_str
109
112
  end
@@ -115,6 +118,7 @@ module Stanford
115
118
  def date_created_elements(ignore_approximate = false)
116
119
  date_created_nodeset = mods_ng_xml.origin_info.dateCreated
117
120
  return self.class.remove_approximate(date_created_nodeset) if ignore_approximate
121
+
118
122
  date_created_nodeset.to_a
119
123
  end
120
124
 
@@ -125,6 +129,7 @@ module Stanford
125
129
  def date_issued_elements(ignore_approximate = false)
126
130
  date_issued_nodeset = mods_ng_xml.origin_info.dateIssued
127
131
  return self.class.remove_approximate(date_issued_nodeset) if ignore_approximate
132
+
128
133
  date_issued_nodeset.to_a
129
134
  end
130
135
 
@@ -194,6 +199,7 @@ module Stanford
194
199
  # @return [Integer, String] year as a String or Integer, depending on method_sym
195
200
  def date_parsing_result(date_el_array, method_sym)
196
201
  return if date_el_array.empty?
202
+
197
203
  # prefer keyDate
198
204
  key_date_el = self.class.keyDate(date_el_array)
199
205
  DateParsing.send(method_sym, key_date_el.content) if key_date_el
@@ -239,6 +245,7 @@ module Stanford
239
245
  return nil unless pub_date
240
246
  return "#{pub_date.to_i + 1000} B.C." if pub_date.start_with?('-')
241
247
  return pub_date unless pub_date.include? '--'
248
+
242
249
  "#{pub_date[0, 2].to_i + 1}th century"
243
250
  end
244
251
 
@@ -251,6 +258,7 @@ module Stanford
251
258
  pd = pd.gsub('--', '00')
252
259
  end
253
260
  fail "pub_date_sort was about to return a non 4 digit value #{pd}!" if pd && pd.length != 4
261
+
254
262
  pd
255
263
  end
256
264
 
@@ -261,6 +269,7 @@ module Stanford
261
269
  def pub_date_display
262
270
  return dates_no_marc_encoding.first unless dates_no_marc_encoding.empty?
263
271
  return dates_marc_encoding.first unless dates_marc_encoding.empty?
272
+
264
273
  nil
265
274
  end
266
275
 
@@ -274,6 +283,7 @@ module Stanford
274
283
  # use the cached year if there is one
275
284
  if @pub_year
276
285
  return nil if @pub_year == ''
286
+
277
287
  return @pub_year
278
288
  end
279
289
 
@@ -307,6 +317,7 @@ module Stanford
307
317
  def pub_dates
308
318
  return dates_marc_encoding unless dates_marc_encoding.empty?
309
319
  return dates_no_marc_encoding unless dates_no_marc_encoding.empty?
320
+
310
321
  nil
311
322
  end
312
323
 
@@ -410,6 +421,7 @@ module Stanford
410
421
  dates.each do |f_date|
411
422
  matches = f_date.scan(/\d{1}th/)
412
423
  next if matches.empty?
424
+
413
425
  if matches.length == 1
414
426
  @pub_year = (matches.first[0, 2].to_i - 1).to_s + '--'
415
427
  return @pub_year
@@ -436,6 +448,7 @@ module Stanford
436
448
  dates.each do |f_date|
437
449
  matches = f_date.scan(/\d{2}th/)
438
450
  next if matches.empty?
451
+
439
452
  if matches.length == 1
440
453
  @pub_year = (matches.first[0, 2].to_i - 1).to_s + '--'
441
454
  return @pub_year
@@ -464,6 +477,7 @@ module Stanford
464
477
  # Single digit u notation
465
478
  matches = f_date.scan(/\d{3}u/)
466
479
  return matches.first.tr('u', '0') if matches.length == 1
480
+
467
481
  # Double digit u notation
468
482
  matches = f_date.scan(/\d{2}u{2}/)
469
483
  return matches.first.tr('u', '-') if matches.length == 1
@@ -139,26 +139,27 @@ module Stanford
139
139
  present_title_info_nodes ? present_title_info_nodes.first : nil
140
140
  end
141
141
 
142
- # @return [String] the nonSort text portion of the titleInfo node as a string (if non-empty, else nil)
142
+ # @return [String] the nonSort text portion of the titleInfo node as a string (if non-empty, else nil)
143
143
  def nonSort_title
144
144
  return unless first_title_info_node && first_title_info_node.nonSort
145
145
 
146
146
  first_title_info_node.nonSort.text.strip.empty? ? nil : first_title_info_node.nonSort.text.strip
147
147
  end
148
-
148
+
149
149
  # @return [String] the text of the titleInfo node as a string (if non-empty, else nil)
150
150
  def title
151
151
  return unless first_title_info_node && first_title_info_node.title
152
152
 
153
153
  first_title_info_node.title.text.strip.empty? ? nil : first_title_info_node.title.text.strip
154
154
  end
155
-
155
+
156
+ # Searchworks requires that the MODS has a '//titleInfo/title'
156
157
  # @return [String] value for title_245_search, title_full_display
157
158
  def sw_full_title
158
-
159
- return nil unless first_title_info_node
159
+ return nil if !first_title_info_node || !title
160
+
160
161
  preSubTitle = nonSort_title ? [nonSort_title, title].compact.join(" ") : title
161
- preSubTitle.sub!(/:$/, '') if preSubTitle # remove trailing colon
162
+ preSubTitle.sub!(/:$/, '')
162
163
 
163
164
  subTitle = first_title_info_node.subTitle.text.strip
164
165
  preParts = subTitle.empty? ? preSubTitle : preSubTitle + " : " + subTitle
@@ -178,6 +179,7 @@ module Stanford
178
179
 
179
180
  result = parts ? preParts + ". " + parts : preParts
180
181
  return nil unless result
182
+
181
183
  result += "." unless result =~ /[[:punct:]]$/
182
184
  result.strip!
183
185
  result = nil if result.empty?
@@ -191,13 +193,20 @@ module Stanford
191
193
  def sw_title_display
192
194
  result = sw_full_title
193
195
  return nil unless result
196
+
194
197
  result.sub(/[\.,;:\/\\]+$/, '').strip
195
198
  end
196
199
 
197
200
  # this includes all titles except
198
201
  # @return [Array<String>] values for title_variant_search
199
202
  def sw_addl_titles
200
- full_titles.select { |s| s !~ Regexp.new(Regexp.escape(sw_short_title)) }
203
+ excluded_title = sw_short_title || sw_title_display
204
+ if excluded_title.present?
205
+ title_regex = Regexp.new(Regexp.escape(excluded_title))
206
+ full_titles.reject { |s| s =~ title_regex }.reject(&:blank?)
207
+ else
208
+ full_titles.reject(&:blank?)
209
+ end
201
210
  end
202
211
 
203
212
  # Returns a sortable version of the main title
@@ -227,68 +236,15 @@ module Stanford
227
236
  # see origin_info.rb (as all this information comes from top level originInfo element)
228
237
  # ---- end PUBLICATION (place, year) ----
229
238
 
230
- # select one or more format values from the controlled vocabulary here:
231
- # http://searchworks-solr-lb.stanford.edu:8983/solr/select?facet.field=format&rows=0&facet.sort=index
232
- # @return <Array[String]> value in the SearchWorks controlled vocabulary
233
- # @deprecated - kept for backwards compatibility but not part of SW UI redesign work Summer 2014
234
- # @deprecated: this is no longer used in SW, Revs or Spotlight Jan 2016
235
- def format
236
- types = term_values(:typeOfResource)
237
- return [] unless types
238
- genres = term_values(:genre)
239
- issuance = term_values([:origin_info, :issuance])
240
- val = []
241
- types.each do |type|
242
- case type
243
- when 'cartographic'
244
- val << 'Map/Globe'
245
- when 'mixed material'
246
- val << 'Manuscript/Archive'
247
- when 'moving image'
248
- val << 'Video'
249
- when 'notated music'
250
- val << 'Music - Score'
251
- when 'software, multimedia'
252
- val << 'Computer File'
253
- when 'sound recording-musical'
254
- val << 'Music - Recording'
255
- when 'sound recording-nonmusical', 'sound recording'
256
- val << 'Sound Recording'
257
- when 'still image'
258
- val << 'Image'
259
- when 'text'
260
- val << 'Book' if issuance && issuance.include?('monographic')
261
- book_genres = ['book chapter', 'Book chapter', 'Book Chapter',
262
- 'issue brief', 'Issue brief', 'Issue Brief',
263
- 'librettos', 'Librettos',
264
- 'project report', 'Project report', 'Project Report',
265
- 'technical report', 'Technical report', 'Technical Report',
266
- 'working paper', 'Working paper', 'Working Paper']
267
- val << 'Book' if genres && !(genres & book_genres).empty?
268
- conf_pub = ['conference publication', 'Conference publication', 'Conference Publication']
269
- val << 'Conference Proceedings' if genres && !(genres & conf_pub).empty?
270
- val << 'Journal/Periodical' if issuance && issuance.include?('continuing')
271
- article = ['article', 'Article']
272
- val << 'Journal/Periodical' if genres && !(genres & article).empty?
273
- stu_proj_rpt = ['student project report', 'Student project report', 'Student Project report', 'Student Project Report']
274
- val << 'Other' if genres && !(genres & stu_proj_rpt).empty?
275
- thesis = ['thesis', 'Thesis']
276
- val << 'Thesis' if genres && !(genres & thesis).empty?
277
- when 'three dimensional object'
278
- val << 'Other'
279
- end
280
- end
281
- val.uniq
282
- end
283
-
284
239
  # select one or more format values from the controlled vocabulary per JVine Summer 2014
285
240
  # http://searchworks-solr-lb.stanford.edu:8983/solr/select?facet.field=format_main_ssim&rows=0&facet.sort=index
286
241
  # https://github.com/sul-dlss/stanford-mods/issues/66 - For geodata, the
287
242
  # resource type should be only Map and not include Software, multimedia.
288
243
  # @return <Array[String]> value in the SearchWorks controlled vocabulary
289
244
  def format_main
290
- types = term_values(:typeOfResource)
245
+ types = typeOfResource
291
246
  return [] unless types
247
+
292
248
  article_genres = ['article', 'Article',
293
249
  'book chapter', 'Book chapter', 'Book Chapter',
294
250
  'issue brief', 'Issue brief', 'Issue Brief',
@@ -303,13 +259,18 @@ module Stanford
303
259
  'thesis', 'Thesis'
304
260
  ]
305
261
  val = []
306
- genres = term_values(:genre)
307
- issuance = term_values([:origin_info, :issuance])
262
+ genres = term_values(:genre) || []
263
+ issuance = term_values([:origin_info, :issuance]) || []
264
+ frequency = term_values([:origin_info, :frequency]) || []
265
+
266
+ val << 'Dataset' if genres.include?('dataset') || genres.include?('Dataset')
267
+
308
268
  types.each do |type|
309
- case type
269
+ val << 'Archive/Manuscript' if type.manuscript == 'yes'
270
+
271
+ case type.text
310
272
  when 'cartographic'
311
273
  val << 'Map'
312
- val.delete 'Software/Multimedia'
313
274
  when 'mixed material'
314
275
  val << 'Archive/Manuscript'
315
276
  when 'moving image'
@@ -317,11 +278,7 @@ module Stanford
317
278
  when 'notated music'
318
279
  val << 'Music score'
319
280
  when 'software, multimedia'
320
- if genres && (genres.include?('dataset') || genres.include?('Dataset'))
321
- val << 'Dataset'
322
- elsif !val.include?('Map')
323
- val << 'Software/Multimedia'
324
- end
281
+ val << 'Software/Multimedia' unless types.map(&:text).include?('cartographic') || (genres.include?('dataset') || genres.include?('Dataset'))
325
282
  when 'sound recording-musical'
326
283
  val << 'Music recording'
327
284
  when 'sound recording-nonmusical', 'sound recording'
@@ -329,11 +286,14 @@ module Stanford
329
286
  when 'still image'
330
287
  val << 'Image'
331
288
  when 'text'
332
- val << 'Book' if genres && !(genres & article_genres).empty?
333
- val << 'Book' if issuance && issuance.include?('monographic')
334
- val << 'Book' if genres && !(genres & book_genres).empty?
335
- val << 'Journal/Periodical' if issuance && issuance.include?('continuing')
336
- val << 'Archived website' if genres && genres.include?('archived website')
289
+ is_explicitly_a_book = type.manuscript != 'yes' && (issuance.include?('monographic') || !(genres & article_genres).empty? || !(genres & book_genres).empty?)
290
+ is_periodical = issuance.include?('continuing') || issuance.include?('serial') || frequency.any? { |x| !x.empty? }
291
+ is_archived_website = genres.any? { |x| x.casecmp('archived website') == 0 }
292
+
293
+ val << 'Book' if is_explicitly_a_book
294
+ val << 'Journal/Periodical' if is_periodical
295
+ val << 'Archived website' if is_archived_website
296
+ val << 'Book' unless is_explicitly_a_book || is_periodical || is_archived_website
337
297
  when 'three dimensional object'
338
298
  val << 'Object'
339
299
  end
@@ -341,24 +301,23 @@ module Stanford
341
301
  val.uniq
342
302
  end
343
303
 
344
- # https://github.com/sul-dlss/stanford-mods/issues/66
345
- # Limit genre values to Government document, Conference proceedings,
346
- # Technical report and Thesis/Dissertation
347
304
  # @return <Array[String]> values for the genre facet in SearchWorks
348
305
  def sw_genre
349
306
  genres = term_values(:genre)
350
307
  return [] unless genres
351
- types = term_values(:typeOfResource)
352
- val = []
353
- val << 'Thesis/Dissertation' if genres.include?('thesis') || genres.include?('Thesis')
354
- if genres && types && types.include?('text')
355
- conf_pub = ['conference publication', 'Conference publication', 'Conference Publication']
356
- gov_pub = ['government publication', 'Government publication', 'Government Publication']
357
- tech_rpt = ['technical report', 'Technical report', 'Technical Report']
358
- val << 'Conference proceedings' unless (genres & conf_pub).empty?
359
- val << 'Government document' unless (genres & gov_pub).empty?
360
- val << 'Technical report' unless (genres & tech_rpt).empty?
361
- end
308
+
309
+ val = genres.map(&:to_s)
310
+ thesis_pub = ['thesis', 'Thesis']
311
+ val << 'Thesis/Dissertation' if (genres & thesis_pub).any?
312
+
313
+ conf_pub = ['conference publication', 'Conference publication', 'Conference Publication']
314
+ gov_pub = ['government publication', 'Government publication', 'Government Publication']
315
+ tech_rpt = ['technical report', 'Technical report', 'Technical Report']
316
+
317
+ val << 'Conference proceedings' if (genres & conf_pub).any?
318
+ val << 'Government document' if (genres & gov_pub).any?
319
+ val << 'Technical report' if (genres & tech_rpt).any?
320
+
362
321
  val.uniq
363
322
  end
364
323
 
@@ -366,6 +325,7 @@ module Stanford
366
325
  def catkey
367
326
  catkey = term_values([:record_info, :recordIdentifier])
368
327
  return nil unless catkey && !catkey.empty?
328
+
369
329
  catkey.first.tr('a', '') # ensure catkey is numeric only
370
330
  end
371
331
  end # class Record