sip2-ruby 0.1.0

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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +136 -0
  4. data/Rakefile +10 -0
  5. data/bin/json-to-sip2 +109 -0
  6. data/bin/sip2-to-json +81 -0
  7. data/lib/sip2/checksum_encoder.rb +11 -0
  8. data/lib/sip2/field_parser_rules.rb +490 -0
  9. data/lib/sip2/fields.rb +742 -0
  10. data/lib/sip2/message/base_message.rb +135 -0
  11. data/lib/sip2/message/unknown_message.rb +26 -0
  12. data/lib/sip2/message.rb +95 -0
  13. data/lib/sip2/message_parser_rules.rb +122 -0
  14. data/lib/sip2/messages.rb +628 -0
  15. data/lib/sip2/parser.rb +14 -0
  16. data/lib/sip2/parser_atoms.rb +53 -0
  17. data/lib/sip2/transformer.rb +94 -0
  18. data/lib/sip2/types.rb +6 -0
  19. data/lib/sip2/version.rb +3 -0
  20. data/lib/sip2.rb +18 -0
  21. data/sip2-ruby.gemspec +39 -0
  22. data/test/fixture_helper.rb +31 -0
  23. data/test/fixtures/09.sip2 +1 -0
  24. data/test/fixtures/10.sip2 +1 -0
  25. data/test/fixtures/17.sip2 +1 -0
  26. data/test/fixtures/18.sip2 +1 -0
  27. data/test/fixtures/98-with-unexpected.sip2 +1 -0
  28. data/test/fixtures/98.sip2 +1 -0
  29. data/test/fixtures/99-with-unexpected.sip2 +1 -0
  30. data/test/fixtures/99.sip2 +1 -0
  31. data/test/fixtures/XX.sip2 +1 -0
  32. data/test/fixtures/alma/09.sip2 +1 -0
  33. data/test/fixtures/alma/10.sip2 +1 -0
  34. data/test/fixtures/alma/17.sip2 +1 -0
  35. data/test/fixtures/alma/18.sip2 +1 -0
  36. data/test/fixtures/alma/98.sip2 +1 -0
  37. data/test/fixtures/alma/99.sip2 +1 -0
  38. data/test/round_trip_spec.rb +82 -0
  39. data/test/sip2/message_parser_rules_spec.rb +50 -0
  40. data/test/sip2/parser_atoms_spec.rb +354 -0
  41. data/test/sip2/parser_test.rb +11 -0
  42. data/test/sip2_spec.rb +145 -0
  43. data/test/spec_helper.rb +4 -0
  44. data/test/test_helper.rb +4 -0
  45. metadata +190 -0
@@ -0,0 +1,490 @@
1
+ require 'parslet'
2
+ require 'sip2/parser_atoms.rb'
3
+
4
+ module Sip2
5
+ module FieldParserRules
6
+ include Parslet
7
+
8
+ include Sip2::ParserAtoms
9
+
10
+ rule(:acs_renewal_policy) {
11
+ bool.as(:acs_renewal_policy)
12
+ }
13
+
14
+ rule(:alert) {
15
+ bool.as(:alert)
16
+ }
17
+
18
+ rule(:available) {
19
+ bool.as(:available)
20
+ }
21
+
22
+ rule(:blocked_card_msg) {
23
+ str("AL") >> variable_length_value.as(:blocked_card_msg)
24
+ }
25
+
26
+ rule(:cancel) {
27
+ str("BI") >> bool.as(:cancel) >> pipe
28
+ }
29
+
30
+ rule(:card_retained) {
31
+ bool.as(:card_retained)
32
+ }
33
+
34
+ rule(:charged_items) {
35
+ str("AU") >> variable_length_value.as(:charged_items)
36
+ }
37
+
38
+ rule(:charged_items_count) {
39
+ four_digits_or_blanks.as(:charged_items_count)
40
+ }
41
+
42
+ rule(:charged_items_limit) {
43
+ str("CB") >> digit.repeat(4,4).as(:int).as(:charged_items_limit) >> pipe
44
+ }
45
+
46
+ rule(:checkin_ok) {
47
+ bool.as(:checkin_ok)
48
+ }
49
+
50
+ rule(:checkout_ok) {
51
+ bool.as(:checkout_ok)
52
+ }
53
+
54
+ rule(:checksum) {
55
+ str("AZ") >> hex_digit.repeat(4,4).as(:str).as(:checksum)
56
+ }
57
+
58
+ rule(:circulation_status) {
59
+ (digit >> digit).as(:int).as(:circulation_status)
60
+ }
61
+
62
+ rule(:currency_type) {
63
+ str("BH") >> match["A-Z"].repeat(3,3).as(:str).as(:currency_type) >> pipe
64
+ }
65
+
66
+ rule(:currency_type_ordered) {
67
+ match["A-Z"].repeat(3,3).as(:str).as(:currency_type)
68
+ }
69
+
70
+ rule(:current_location) {
71
+ str("AP") >> variable_length_value.as(:current_location)
72
+ }
73
+
74
+ rule(:date_time_sync) {
75
+ timestamp.as(:date_time_sync)
76
+ }
77
+
78
+ rule(:desensitize) {
79
+ nillable_bool.as(:desensitize)
80
+ }
81
+
82
+ rule(:due_date) {
83
+ str("AH") >> variable_length_value.as(:due_date)
84
+ }
85
+
86
+ rule(:email_address) {
87
+ str("BE") >> variable_length_value.as(:email_address)
88
+ }
89
+
90
+ rule(:end_item) {
91
+ str("BQ") >> variable_length_value.as(:end_item)
92
+ }
93
+
94
+ rule(:end_session) {
95
+ bool.as(:end_session)
96
+ }
97
+
98
+ rule(:expiration_date) {
99
+ str("BW") >> timestamp.as(:expiration_date) >> pipe
100
+ }
101
+
102
+ rule(:fee_acknowledged) {
103
+ str("BO") >> bool.as(:fee_acknowledged) >> pipe
104
+ }
105
+
106
+ rule(:fee_amount) {
107
+ str("BV") >> variable_length_value.as(:fee_amount)
108
+ }
109
+
110
+ rule(:fee_identifier) {
111
+ str("CG") >> variable_length_value.as(:fee_identifier)
112
+ }
113
+
114
+ rule(:fee_limit) {
115
+ str("CC") >> variable_length_value.as(:fee_limit)
116
+ }
117
+
118
+ rule(:fee_type) {
119
+ str("BT") >> ((zero >> natural) | (natural >> digit)).as(:int).as(:fee_type) >> pipe
120
+ }
121
+
122
+ rule(:fee_type_ordered) {
123
+ ((zero >> natural) | (natural >> digit)).as(:int).as(:fee_type)
124
+ }
125
+
126
+ rule(:fine_items) {
127
+ str("AV") >> variable_length_value.as(:fine_items)
128
+ }
129
+
130
+ rule(:fine_items_count) {
131
+ four_digits_or_blanks.as(:fine_items_count)
132
+ }
133
+
134
+ rule(:hold_items) {
135
+ str("AS") >> variable_length_value.as(:hold_items)
136
+ }
137
+
138
+ rule(:hold_items_count) {
139
+ four_digits_or_blanks.as(:hold_items_count)
140
+ }
141
+
142
+ rule(:hold_items_limit) {
143
+ str("BZ") >> digit.repeat(4,4).as(:int).as(:hold_items_limit) >> pipe
144
+ }
145
+
146
+ rule(:hold_mode) {
147
+ (str("+") | str("-") | str("*")).as(:str).as(:hold_mode)
148
+ }
149
+
150
+ rule(:hold_pickup_date) {
151
+ str("CM") >> timestamp.as(:hold_pickup_date) >> pipe
152
+ }
153
+
154
+ rule(:hold_queue_length) {
155
+ str("CF") >> variable_length_value.as(:hold_queue_length)
156
+ }
157
+
158
+ rule(:hold_type) {
159
+ str("BY") >> natural.as(:int).as(:hold_type) >> pipe
160
+ }
161
+
162
+ rule(:home_address) {
163
+ str("BD") >> variable_length_value.as(:home_address)
164
+ }
165
+
166
+ rule(:home_phone_number) {
167
+ str("BF") >> variable_length_value.as(:home_phone_number)
168
+ }
169
+
170
+ rule(:institution_id) {
171
+ str("AO") >> variable_length_value.as(:institution_id)
172
+ }
173
+
174
+ rule(:item_identifier) {
175
+ str("AB") >> variable_length_value.as(:item_identifier)
176
+ }
177
+
178
+ rule(:item_properties) {
179
+ str("CH") >> variable_length_value.as(:item_properties)
180
+ }
181
+
182
+ rule(:item_properties_ok) {
183
+ any_valid.as(:numerical_bool).as(:item_properties_ok)
184
+ }
185
+
186
+ rule(:items) {
187
+ (
188
+ hold_items.repeat(1).as(:hold_items) |
189
+ overdue_items.repeat(1).as(:overdue_items) |
190
+ charged_items.repeat(1).as(:charged_items) |
191
+ fine_items.repeat(1).as(:fine_items) |
192
+ recall_items.repeat(1).as(:recall_items) |
193
+ unavailable_hold_items.repeat(1).as(:unavailable_hold_items)
194
+ ).as(:items)
195
+ }
196
+
197
+ rule(:language) {
198
+ digit.repeat(3,3).as(:int).as(:language)
199
+ }
200
+
201
+ rule(:library_name) {
202
+ str("AM") >> variable_length_value.as(:library_name)
203
+ }
204
+
205
+ rule(:location_code) {
206
+ str("CP") >> variable_length_value.as(:location_code)
207
+ }
208
+
209
+ rule(:login_password) {
210
+ str("CO") >> variable_length_value.as(:login_password)
211
+ }
212
+
213
+ rule(:login_user_id) {
214
+ str("CN") >> variable_length_value.as(:login_user_id)
215
+ }
216
+
217
+ rule(:magnetic_media) {
218
+ nillable_bool.as(:magnetic_media)
219
+ }
220
+
221
+ rule(:max_print_width) {
222
+ digit.repeat(3,3).as(:int).as(:max_print_width)
223
+ }
224
+
225
+ rule(:media_type) {
226
+ str("CK") >> digit.repeat(3,3).as(:int).as(:media_type) >> pipe
227
+ }
228
+
229
+ rule(:nb_due_date) {
230
+ (timestamp | space.repeat(18,18).as(:nil)).as(:nb_due_date)
231
+ }
232
+
233
+ rule(:no_block) {
234
+ bool.as(:no_block)
235
+ }
236
+
237
+ rule(:offline_ok) {
238
+ bool.as(:offline_ok)
239
+ }
240
+
241
+ rule(:ok) {
242
+ numerical_bool.as(:ok)
243
+ }
244
+
245
+ rule(:online_status) {
246
+ bool.as(:online_status)
247
+ }
248
+
249
+ rule(:overdue_items) {
250
+ str("AT") >> variable_length_value.as(:overdue_items)
251
+ }
252
+
253
+ rule(:overdue_items_count) {
254
+ four_digits_or_blanks.as(:overdue_items_count)
255
+ }
256
+
257
+ rule(:overdue_items_limit) {
258
+ str("CA") >> digit.repeat(4,4).as(:int).as(:overdue_items_limit) >> pipe
259
+ }
260
+
261
+ rule(:owner) {
262
+ str("BG") >> variable_length_value.as(:owner)
263
+ }
264
+
265
+ rule(:patron_identifier) {
266
+ str("AA") >> variable_length_value.as(:patron_identifier)
267
+ }
268
+
269
+ rule(:patron_password) {
270
+ str("AD") >> variable_length_value.as(:patron_password)
271
+ }
272
+
273
+ rule(:patron_status) {
274
+ (
275
+ bool_with_space.as(:charge_privileges_denied) >>
276
+ bool_with_space.as(:renewal_privileges_denied) >>
277
+ bool_with_space.as(:recall_privileges_denied) >>
278
+ bool_with_space.as(:hold_privileges_denied) >>
279
+ bool_with_space.as(:card_reported_lost) >>
280
+ bool_with_space.as(:too_many_items_charged) >>
281
+ bool_with_space.as(:too_many_items_overdue) >>
282
+ bool_with_space.as(:too_many_renewals) >>
283
+ bool_with_space.as(:too_many_claims_of_items_returned) >>
284
+ bool_with_space.as(:too_many_items_lost) >>
285
+ bool_with_space.as(:excessive_outstanding_fines) >>
286
+ bool_with_space.as(:excessive_outstanding_fees) >>
287
+ bool_with_space.as(:recall_overdue) >>
288
+ bool_with_space.as(:too_many_items_billed)
289
+ ).as(:patron_status)
290
+ }
291
+
292
+ rule(:payment_accepted) {
293
+ bool.as(:payment_accepted)
294
+ }
295
+
296
+ rule(:payment_type) {
297
+ (digit >> digit).as(:int).as(:payment_type)
298
+ }
299
+
300
+ rule(:permanent_location) {
301
+ str("AQ") >> variable_length_value.as(:permanent_location)
302
+ }
303
+
304
+ rule(:personal_name) {
305
+ str("AE") >> variable_length_value.as(:personal_name)
306
+ }
307
+
308
+ rule(:pickup_location) {
309
+ str("BS") >> variable_length_value.as(:pickup_location)
310
+ }
311
+
312
+ rule(:print_line) {
313
+ str("AG") >> variable_length_value.as(:print_line).as(:merge_repeat_to_array)
314
+ }
315
+
316
+ rule(:protocol_version) {
317
+ (digit >> str(".") >> digit >> digit).as(:str).as(:protocol_version)
318
+ }
319
+
320
+ rule(:pwd_algorithm) {
321
+ any_valid.as(:str).as(:pwd_algorithm)
322
+ }
323
+
324
+ rule(:queue_position) {
325
+ str("BR") >> digit.repeat.as(:int).as(:queue_position) >> pipe
326
+ }
327
+
328
+ rule(:recall_date) {
329
+ str("CJ") >> timestamp.as(:recall_date) >> pipe
330
+ }
331
+
332
+ rule(:recall_items) {
333
+ str("BU") >> variable_length_value.as(:recall_items)
334
+ }
335
+
336
+ rule(:recall_items_count) {
337
+ four_digits_or_blanks.as(:recall_items_count)
338
+ }
339
+
340
+ rule(:renewal_ok) {
341
+ bool.as(:renewal_ok)
342
+ }
343
+
344
+ rule(:renewed_count) {
345
+ digit.repeat(4,4).as(:int).as(:renewed_count)
346
+ }
347
+
348
+ rule(:renewed_items) {
349
+ str("BM") >> variable_length_value.as(:renewed_items)
350
+ }
351
+
352
+ rule(:resensitize) {
353
+ bool.as(:resensitize)
354
+ }
355
+
356
+ rule(:retries_allowed) {
357
+ digit.repeat(3,3).as(:int).as(:retries_allowed)
358
+ }
359
+
360
+ rule(:return_date) {
361
+ timestamp.as(:return_date)
362
+ }
363
+
364
+ rule(:sc_renewal_policy) {
365
+ bool.as(:sc_renewal_policy)
366
+ }
367
+
368
+ rule(:screen_message) {
369
+ str("AF") >> variable_length_value.as(:screen_message).as(:merge_repeat_to_array)
370
+ }
371
+
372
+ rule(:security_inhibit) {
373
+ str("CI") >> bool.as(:security_inhibit) >> pipe
374
+ }
375
+
376
+ rule(:security_marker) {
377
+ (digit >> digit).as(:int).as(:security_marker)
378
+ }
379
+
380
+ rule(:sequence_number) {
381
+ str("AY") >> digit.as(:int).as(:sequence_number)
382
+ }
383
+
384
+ rule(:sort_bin) {
385
+ str("CL") >> variable_length_value.as(:sort_bin)
386
+ }
387
+
388
+ rule(:start_item) {
389
+ str("BP") >> variable_length_value.as(:start_item)
390
+ }
391
+
392
+ rule(:status_code) {
393
+ match["012"].as(:int).as(:status_code)
394
+ }
395
+
396
+ rule(:status_update_ok) {
397
+ bool.as(:status_update_ok)
398
+ }
399
+
400
+ rule(:summary) {
401
+ (
402
+ bool_with_space.as(:hold_items) >>
403
+ bool_with_space.as(:overdue_items) >>
404
+ bool_with_space.as(:charged_items) >>
405
+ bool_with_space.as(:fine_items) >>
406
+ bool_with_space.as(:recall_items) >>
407
+ bool_with_space.as(:unavailable_holds) >>
408
+ match["Y "].repeat(4,4)
409
+ ).as(:summary)
410
+ }
411
+
412
+ rule(:supported_messages) {
413
+ str("BX") >>
414
+ (
415
+ bool.as(:patron_status_request) >>
416
+ bool.as(:checkout) >>
417
+ bool.as(:checkin) >>
418
+ bool.as(:block_patron) >>
419
+ bool.as(:sc_acs_status) >>
420
+ bool.as(:request_sc_asc_resend) >>
421
+ bool.as(:login) >>
422
+ bool.as(:patron_information) >>
423
+ bool.as(:end_patron_session) >>
424
+ bool.as(:fee_paid) >>
425
+ bool.as(:item_information) >>
426
+ bool.as(:item_status_update) >>
427
+ bool.as(:patron_enable) >>
428
+ bool.as(:hold) >>
429
+ bool.as(:renew) >>
430
+ bool.as(:renew_all)
431
+ ).as(:supported_messages) >> pipe
432
+ }
433
+
434
+ rule(:terminal_location) {
435
+ str("AN") >> variable_length_value.as(:terminal_location)
436
+ }
437
+
438
+ rule(:terminal_password) {
439
+ str("AC") >> variable_length_value.as(:terminal_password)
440
+ }
441
+
442
+ rule(:third_party_allowed) {
443
+ bool.as(:third_party_allowed)
444
+ }
445
+
446
+ rule(:timeout_period) {
447
+ digit.repeat(3,3).as(:int).as(:timeout_period)
448
+ }
449
+
450
+ rule(:title_identifier) {
451
+ str("AJ") >> variable_length_value.as(:title_identifier)
452
+ }
453
+
454
+ rule(:transaction_date) {
455
+ timestamp.as(:transaction_date)
456
+ }
457
+
458
+ rule(:transaction_id) {
459
+ str("BK") >> variable_length_value.as(:transaction_id)
460
+ }
461
+
462
+ rule(:uid_algorithm) {
463
+ any_valid.as(:str).as(:uid_algorithm)
464
+ }
465
+
466
+ rule(:unavailable_holds_count) {
467
+ four_digits_or_blanks.as(:unavailable_holds_count)
468
+ }
469
+
470
+ rule(:unavailable_hold_items) {
471
+ str("CD") >> variable_length_value.as(:unavailable_hold_items)
472
+ }
473
+
474
+ rule(:unrenewed_count) {
475
+ digit.repeat(4,4).as(:int).as(:unrenewed_count)
476
+ }
477
+
478
+ rule(:unrenewed_items) {
479
+ str("BN") >> variable_length_value.as(:unrenewed_items)
480
+ }
481
+
482
+ rule(:valid_patron) {
483
+ str("BL") >> bool.as(:valid_patron) >> pipe
484
+ }
485
+
486
+ rule(:valid_patron_password) {
487
+ str("CQ") >> bool.as(:valid_patron_password) >> pipe
488
+ }
489
+ end
490
+ end