voyager_api 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,7 +1,8 @@
1
1
  source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
- # gem "activesupport", ">= 2.3.5"
4
+ gem "activesupport"
5
+ gem 'i18n'
5
6
 
6
7
  gem "httpclient"
7
8
  gem "nokogiri"
data/Gemfile.lock CHANGED
@@ -1,6 +1,8 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
+ activesupport (3.1.0)
5
+ multi_json (~> 1.0)
4
6
  git (1.2.5)
5
7
  growl (1.0.3)
6
8
  guard (0.6.3)
@@ -8,6 +10,7 @@ GEM
8
10
  guard-minitest (0.4.0)
9
11
  guard (~> 0.4)
10
12
  httpclient (2.2.1)
13
+ i18n (0.6.0)
11
14
  jeweler (1.6.4)
12
15
  bundler (~> 1.0)
13
16
  git (>= 1.2.5)
@@ -16,6 +19,7 @@ GEM
16
19
  minitest (2.5.1)
17
20
  mocha (0.10.0)
18
21
  metaclass (~> 0.0.1)
22
+ multi_json (1.0.3)
19
23
  nokogiri (1.5.0)
20
24
  rake (0.9.2)
21
25
  rb-fsevent (0.4.3.1)
@@ -26,10 +30,12 @@ PLATFORMS
26
30
  ruby
27
31
 
28
32
  DEPENDENCIES
33
+ activesupport
29
34
  bundler (~> 1.0.0)
30
35
  growl
31
36
  guard-minitest
32
37
  httpclient
38
+ i18n
33
39
  jeweler (~> 1.6.4)
34
40
  minitest
35
41
  mocha
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -0,0 +1,172 @@
1
+ 1n:
2
+ short_message: Available
3
+ long_message: Not checked out
4
+ 1r:
5
+ short_message: 'Available (Requests: %REQS)'
6
+ long_message: 'Not checked out (Requests: %REQS)'
7
+ 2n:
8
+ short_message: 'Checked out, due %DATE'
9
+ long_message: 'Checked out, due %DATE - Recall, or try Borrow Direct or ILL.'
10
+ services:
11
+ - recall_hold
12
+ - borrow_direct
13
+ - ill
14
+ 2r:
15
+ short_message: 'Checked out, due %DATE (Requests: %REQS)'
16
+ long_message: 'Checked out, due %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
17
+ services:
18
+ - borrow_direct
19
+ - ill
20
+ 3n:
21
+ short_message: 'Checked out, due %DATE'
22
+ long_message: 'Checked out, due %DATE - Recall, or try Borrow Direct or ILL.'
23
+ services:
24
+ - recall_hold
25
+ - borrow_direct
26
+ - ill
27
+ 3r:
28
+ short_message: 'Checked out, due %DATE (Requests: %REQS)'
29
+ long_message: 'Checked out, due %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
30
+ services:
31
+ - borrow_direct
32
+ - ill
33
+ 4n:
34
+ short_message: 'Overdue as of %DATE'
35
+ long_message: 'Overdue as of %DATE - Recall, or try Borrow Direct.'
36
+ services:
37
+ - recall_hold
38
+ - borrow_direct
39
+ 4r:
40
+ short_message: 'Overdue as of %DATE (Requests: %REQS)'
41
+ long_message: 'Overdue as of %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
42
+ services:
43
+ - borrow_direct
44
+ - ill
45
+ 5n:
46
+ short_message: 'Requests: %REQS'
47
+ long_message: 'Requests: %REQS'
48
+ 5r:
49
+ short_message: 'Checked out, due %DATE (Requests: %REQS)'
50
+ long_message: 'Checked out, due %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
51
+ services:
52
+ - borrow_direct
53
+ - ill
54
+ 6n:
55
+ short_message: 'Requests: %REQS'
56
+ long_message: 'Requests: %REQS'
57
+ 6r:
58
+ short_message: 'Checked out, due %DATE (Requests: %REQS)'
59
+ long_message: 'Checked out, due %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
60
+ services:
61
+ - borrow_direct
62
+ - ill
63
+ 7n:
64
+ short_message: 'On hold at %LOC'
65
+ long_message: 'On hold at %LOC. Try Borrow Direct or ILL.'
66
+ services:
67
+ - borrow_direct
68
+ - ill
69
+ 7r:
70
+ short_message: 'On hold at %LOC (Requests: %REQS)'
71
+ long_message: 'On hold at %LOC (Requests: %REQS). Try Borrow Direct or ILL.'
72
+ services:
73
+ - borrow_direct
74
+ - ill
75
+ 8n:
76
+ short_message: 'In transit %DATE'
77
+ long_message: 'In transit %DATE. Place a hold request.'
78
+ services:
79
+ - recall_hold
80
+ 8r:
81
+ short_message: 'In transit %DATE (Requests: %REQS)'
82
+ long_message: 'In transit %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
83
+ services:
84
+ - borrow_direct
85
+ - ill
86
+ 9n:
87
+ short_message: 'In transit to %LOC %DATE'
88
+ long_message: 'In transit to %LOC %DATE. Place a hold request.'
89
+ services:
90
+ - recall_hold
91
+ 9r:
92
+ short_message: 'In transit to %LOC %DATE (Requests: %REQS)'
93
+ long_message: 'In transit to %LOC %DATE (Requests: %REQS). Try Borrow Direct.'
94
+ services:
95
+ - borrow_direct
96
+ 10n:
97
+ short_message: 'In transit to %LOC %DATE. Place a hold request.'
98
+ long_message: 'In transit to %LOC %DATE. Place a hold request.'
99
+ services:
100
+ - recall_hold
101
+ 10r:
102
+ short_message: 'In transit to %LOC %DATE (Requests: %REQS)'
103
+ long_message: 'In transit to %LOC %DATE (Requests: %REQS). Try Borrow Direct.'
104
+ services:
105
+ - borrow_direct
106
+ 11n:
107
+ short_message: 'Returned %DATE'
108
+ long_message: 'Returned %DATE'
109
+ 11r:
110
+ short_message: 'Returned %DATE (Requests: %REQS)'
111
+ long_message: 'Returned %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
112
+ services:
113
+ - borrow_direct
114
+ - ill
115
+ 12n:
116
+ short_message: 'Missing %DATE'
117
+ long_message: 'Missing %DATE. Try Borrow Direct or ILL.'
118
+ services:
119
+ - borrow_direct
120
+ - ill
121
+ 12r:
122
+ short_message: 'Missing %DATE (Requests: %REQS)'
123
+ long_message: 'Missing %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
124
+ services:
125
+ - borrow_direct
126
+ - ill
127
+ 13n:
128
+ short_message: 'Unavailable %DATE'
129
+ long_message: 'Unavailable %DATE. Try Borrow Direct or ILL.'
130
+ services:
131
+ - borrow_direct
132
+ - ill
133
+ 13r:
134
+ short_message: 'Unavailable %DATE (Requests: %REQS)'
135
+ long_message: 'Unavailable %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
136
+ services:
137
+ - borrow_direct
138
+ - ill
139
+ 14n:
140
+ short_message: 'Unavailable %DATE'
141
+ long_message: 'Unavailable %DATE. Try Borrow Direct or ILL.'
142
+ services:
143
+ - borrow_direct
144
+ - ill
145
+ 14r:
146
+ short_message: 'Unavailable %DATE (Requests: %REQS)'
147
+ long_message: 'Unavailable %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
148
+ services:
149
+ - borrow_direct
150
+ - ill
151
+ 18n:
152
+ short_message: 'Sent to bindery for 1 month on %DATE'
153
+ long_message: 'Sent to bindery for 1 month on %DATE. Try Borrow Direct or ILL. '
154
+ services:
155
+ - borrow_direct
156
+ - ill
157
+ 18r:
158
+ short_message: 'Sent to bindery for 1 month on %DATE (Requests: %REQS)'
159
+ long_message: 'Sent to bindery for 1 month on %DATE (Requests: %REQS). Try Borrow Direct or ILL.'
160
+ services:
161
+ - borrow_direct
162
+ - ill
163
+ 22n:
164
+ short_message: 'In Process %DATE'
165
+ long_message: 'In Process %DATE. Place an In Process item request.'
166
+ services:
167
+ - in_process
168
+ 22r:
169
+ short_message: 'In Process %DATE (Requests: %REQS)'
170
+ long_message: 'In Process %DATE (Requests: %REQS). Place an In Process item request.'
171
+ services:
172
+ - in_process
@@ -0,0 +1,25 @@
1
+ '0':
2
+ short_message: 'In the Pre-Order Process'
3
+ long_message: 'In the Pre-Order Process. Try Borrow Direct or ILL.'
4
+ services:
5
+ - borrow_direct
6
+ - ill
7
+ '1':
8
+ short_message: 'Received %DATE'
9
+ long_message: 'Received %DATE. Place an In Process item request.'
10
+ services:
11
+ - in_process
12
+ '4':
13
+ short_message: 'Not yet received; claimed %DATE'
14
+ long_message: 'Not yet received; claimed %DATE. Try Borrow Direct or ILL.'
15
+ services:
16
+ - on_order
17
+ - borrow_direct
18
+ - ill
19
+ '8':
20
+ short_message: 'Copy On Order %DATE'
21
+ long_message: 'Copy On Order %DATE. Try Borrow Direct or ILL.'
22
+ services:
23
+ - on_order
24
+ - borrow_direct
25
+ - ill
@@ -18,12 +18,41 @@ module Voyager
18
18
  end
19
19
 
20
20
  # Generate output hash from Record class instances
21
- def to_hash
21
+ def to_hash(options = {})
22
+ options.reverse_merge!(:output_type => :raw, :content_type => :full, :message_type => :long_message)
23
+
24
+ # :output_type --> :raw (default) | :condensed
25
+ #
26
+ # if :output_type == :condensed
27
+ # :content_type --> :brief | :full (default)
28
+ # :brief --> basic elements: currently location_name, call_number, overall location status, services
29
+ # :full --> all elements
30
+ # if :content_type == :full
31
+ # :message_type --> :short_message | :long_message (default)
32
+ #
33
+
34
+ raise ":output_type not defined" unless options[:output_type] == :raw || options[:output_type] == :condensed
35
+ raise ":content_type not defined" unless options[:content_type] == :full || options[:content_type] == :brief
36
+ raise ":message_type not defined" unless options[:message_type] == :long_message || options[:message_type] == :short_message
37
+
22
38
  output = {}
23
- output[:records] = @records.collect do |rec|
24
- rec.to_hash
39
+
40
+ case options[:output_type]
41
+ when :raw
42
+ output[:records] = @records.collect { |rec| rec.to_hash }
43
+ when :condensed
44
+ # convert @records into a holdings hash
45
+ holdings = @records.collect { |rec| rec.to_hash }
46
+ case options[:content_type]
47
+ when :full
48
+ output[:condensed_holdings_full] = condense_holdings(holdings,options)
49
+ when :brief
50
+ output[:condensed_holdings_brief] = condense_holdings(holdings,options)
51
+ end
25
52
  end
53
+
26
54
  output
55
+
27
56
  end
28
57
 
29
58
  private
@@ -44,6 +73,203 @@ module Voyager
44
73
  Record.new(record_node)
45
74
  end
46
75
  end
76
+
77
+ def condense_holdings(holdings,options)
78
+
79
+ # processing varies depending on complexity
80
+ complexity = determine_complexity(holdings)
81
+ process_holdings(holdings,complexity,options)
82
+
83
+ end
84
+
85
+ def determine_complexity(holdings)
86
+
87
+ # holdings are complex if anything other than item_status has a value
88
+
89
+ complexity = :complex
90
+
91
+ holdings.each do |holding|
92
+ if [:summary_holdings, :supplements, :indexes, :notes,
93
+ :reproduction_note, :current_issues, :temp_locations,
94
+ :orders].all? { |key| holding[key].empty?}
95
+ complexity = :simple
96
+ end
97
+ end
98
+
99
+ complexity
100
+
101
+ end
102
+
103
+ def process_holdings(holdings,complexity,options)
104
+
105
+ entries = []
106
+ holdings.each do |holding|
107
+ # test for location and call number
108
+ entry = entries.find { |entry| entry[:location_name] == holding[:location_name] &&
109
+ entry[:call_number] == holding[:call_number] }
110
+
111
+ unless entry
112
+ entry = {
113
+ :location_name => holding[:location_name],
114
+ :call_number => holding[:call_number],
115
+ :status => '',
116
+ :copies => [],
117
+ :services => []
118
+ }
119
+ entry[:copies] << {:items => {}} if complexity == :simple
120
+ entries << entry
121
+ end
122
+
123
+ # for simple holdings put consolidated status information in the first copy
124
+ if complexity == :simple
125
+ item_status = holding[:item_status]
126
+ messages = item_status[:messages]
127
+ messages.each do |message|
128
+ text = message[options[:message_type]]
129
+ if entry[:copies].first[:items].has_key?(text)
130
+ entry[:copies].first[:items][text][:count] += 1
131
+ else
132
+ entry[:copies].first[:items][text] = {
133
+ :status => item_status[:status],
134
+ :count => 1
135
+ }
136
+ end
137
+ end
138
+ # for complex holdings create hash of elements for each copy and add to entry :copies array
139
+ else
140
+ out = {}
141
+ # process status messages
142
+ item_status = holding[:item_status]
143
+ messages = item_status[:messages]
144
+ out[:items] = {}
145
+ messages.each do |message|
146
+ text = message[options[:message_type]]
147
+ if out[:items].has_key?(text)
148
+ out[:items][text][:count] += 1
149
+ else
150
+ out[:items][text] = {
151
+ :status => item_status[:status],
152
+ :count => 1
153
+ }
154
+ end
155
+ end
156
+ # add other elements to :copies array
157
+ [:current_issues, :indexes, :notes, :orders, :reproduction_note, :supplements,
158
+ :summary_holdings, :temp_locations].each { |type| add_holdings_elements(out,holding,type,options[:message_type]) }
159
+
160
+ entry[:copies] << out
161
+
162
+ end
163
+
164
+ entry[:services] << holding[:services]
165
+
166
+ end
167
+
168
+ # get overall status of each location entry
169
+ entries.each { |entry| determine_overall_status(entry) }
170
+
171
+ # condense services list
172
+ entries.each { |entry| entry[:services] = entry[:services].flatten.uniq }
173
+
174
+ output_condensed_holdings(entries,options[:content_type])
175
+
176
+ end
177
+
178
+ def add_holdings_elements(out,holding,type,message_type)
179
+
180
+ case type
181
+ when :current_issues
182
+ out[type] = "Current Issues: " + holding[type].join('; ') unless holding[type].empty?
183
+ when :indexes
184
+ out[type] = "Indexes: " + holding[type].join(' ') unless holding[type].empty?
185
+ when :notes
186
+ out[type] = "Notes: " + holding[type].join(' ') unless holding[type].empty?
187
+ when :orders
188
+ unless holding[type].empty?
189
+ messages = holding[type].each.collect { |message| message[message_type] }
190
+ out[type] = "Order Information: " + messages.join('; ')
191
+ end
192
+ when :reproduction_note
193
+ out[type] = holding[type] unless holding[type].empty?
194
+ when :supplements
195
+ out[type] = "Supplements: " + holding[type].join(' ') unless holding[type].empty?
196
+ when :summary_holdings
197
+ out[type] = "Library has: " + holding[type].join(' ') unless holding[type].empty?
198
+ when :temp_locations
199
+ out[type] = holding[type] unless holding[type].empty?
200
+ else
201
+ end
202
+
203
+ end
204
+
205
+ def determine_overall_status(entry)
206
+
207
+ a = 0 # available
208
+ s = 0 # some available
209
+ n = 0 # not available
210
+
211
+ status = ''
212
+
213
+ entry[:copies].each do |copy|
214
+ copy[:items].each_pair do |message,details|
215
+ a = 1 if details[:status] == 'available'
216
+ s = 2 if details[:status] == 'some_available'
217
+ n = 4 if details[:status] == 'not_available'
218
+ end
219
+ end
220
+
221
+ # | some | not
222
+ # available (1) | available (2) | available (4) total (a+s+n)
223
+ # -----------------------------------------------------------------
224
+ # Y Y Y 7
225
+ # Y Y N 3
226
+ # Y N Y 5
227
+ # Y N N 1
228
+ # N Y Y 6
229
+ # N Y N 2
230
+ # N N Y 4
231
+ # N N N 0
232
+ #
233
+ # :available is returned if all items are available (1).
234
+ # :not_available is returned if everything is unavailable (4).
235
+ # :none is returned if there is no status (0).
236
+ # otherwise :some_available is returned:
237
+ # All status are checked; as long as something is available, even if
238
+ # there are some items check out, :some_available is returned.
239
+ #
240
+
241
+ case a + s + n
242
+ when 0
243
+ status = 'none'
244
+ status = 'online' if entry[:location_name].match(/^Online/)
245
+ when 1
246
+ status = 'available'
247
+ when 4
248
+ status = 'not_available'
249
+ else
250
+ status = 'some_available'
251
+ end
252
+
253
+ entry[:status] = status
254
+
255
+ end
256
+
257
+ def output_condensed_holdings(entries,type)
258
+
259
+ case type
260
+ when :full
261
+ entries
262
+ when :brief
263
+ entries.collect do |entry|
264
+ {:location_name => entry[:location_name],
265
+ :call_number => entry[:call_number],
266
+ :status => entry[:status],
267
+ :services => entry[:services]}
268
+ end
269
+ end
270
+
271
+ end
272
+
47
273
  end
48
274
  end
49
275
  end