onix 0.4.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.
data/CHANGELOG ADDED
@@ -0,0 +1,30 @@
1
+ v0.4.0 (28th October 2008)
2
+ - Major rework: now based on ROXML instead of xml-mapping
3
+ - Mostly API Compatible
4
+ - StreamReader and StreamWriter renamed to Reader and Writer
5
+ - ROXML is based on libxml, so things should be significantly faster
6
+
7
+ v0.2.7 (Unreleased)
8
+ - Add line breaks after each product
9
+
10
+ v0.2.5 (Unreleased)
11
+ - Make PublishingStatus a two_digit_node
12
+
13
+ v0.2.4 (Unreleased)
14
+ - Initialise the media files array of a new product correctly
15
+
16
+ v0.2.3 (Unreleased)
17
+ - Switch a few more fields over to TwoDigitNodes
18
+ - Make the product availability field accessible from APAProduct
19
+
20
+ v0.2.2 (Unreleased)
21
+ - Add a new nodetype (DateNode) for YYYYMMDD fields
22
+
23
+ v0.2.1 (Unreleased)
24
+ - Add a new nodetype (TwoDigitNode) for two digit codes
25
+
26
+ v0.2.0 (16th July 2008)
27
+ - Add support for reading and storing subject codes (BIC, BISAC, etc)
28
+
29
+ v0.1.0 (12th June 2008)
30
+ - Initial Release
data/README.rdoc ADDED
@@ -0,0 +1,30 @@
1
+ == ONIX
2
+
3
+ The ONIX standard is a somewhat verbose XML format that is rapidly becoming the
4
+ industry standard for electronic data sharing in the book and publishing
5
+ industries.
6
+
7
+ This library provides a slim layer over the format and simplifies both reading
8
+ and writing ONIX files in your ruby applications.
9
+
10
+ == Installation
11
+
12
+ gem install onix
13
+
14
+ == Usage
15
+
16
+ See files in the examples directory to get started quickly. For further reading
17
+ view the comments to the following classes:
18
+
19
+ * ONIX::Reader - For reading ONIX files
20
+ * ONIX::Writer - For writing ONIX files
21
+
22
+ == Contributing
23
+
24
+ All suggestions and patches welcome, preferably via a git repository I can pull from.
25
+
26
+ == Further Reading
27
+
28
+ - The source: (http://github.com/yob/onix/tree/master)[http://github.com/yob/onix/tree/master]
29
+ - Rubyforge project: (http://rubyforge.org/projects/rbook/)[http://rubyforge.org/projects/rbook/]
30
+ - The official specs (http://www.editeur.org/onix.html)[http://www.editeur.org/onix.html]
data/TODO ADDED
@@ -0,0 +1,14 @@
1
+ - finish adding support for all tags in a Product record
2
+ - contributor still needs some obscure tags added
3
+ - add a new node type for dates that should be in the form YYYYMMDD
4
+ - allow symbols to be used instead of numeric codes
5
+ - contribution type, id type, etc
6
+ - validations
7
+ - hard stuff from the spec
8
+ - 2 digit numbers, 8 digit dates, char limits on text fields
9
+ - code lists
10
+ - only values in code lists allowed in relevant fields
11
+ - regional requirements
12
+ - titlepage minimum set of tags
13
+ - APA (if different to titlepage)
14
+ - documentation
data/lib/onix.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+
3
+ # ensure we load the correct gem versions
4
+ gem 'yob-roxml', '2.1.1'
5
+ gem 'andand'
6
+
7
+ # and now load the actual gems
8
+ require 'roxml'
9
+ require 'andand'
10
+
11
+ # custom xml-mapping node types
12
+ require File.join(File.dirname(__FILE__), "onix", "etext_type")
13
+ require File.join(File.dirname(__FILE__), "onix", "integer_type")
14
+ require File.join(File.dirname(__FILE__), "onix", "two_digit_type")
15
+ require File.join(File.dirname(__FILE__), "onix", "date_type")
16
+
17
+ # core files
18
+ # - ordering is important, classes need to be defined before any
19
+ # other class can use them
20
+ require File.join(File.dirname(__FILE__), "onix", "sender_identifier")
21
+ require File.join(File.dirname(__FILE__), "onix", "addressee_identifier")
22
+ require File.join(File.dirname(__FILE__), "onix", "header")
23
+ require File.join(File.dirname(__FILE__), "onix", "product_identifier")
24
+ require File.join(File.dirname(__FILE__), "onix", "title")
25
+ require File.join(File.dirname(__FILE__), "onix", "website")
26
+ require File.join(File.dirname(__FILE__), "onix", "contributor")
27
+ require File.join(File.dirname(__FILE__), "onix", "subject")
28
+ require File.join(File.dirname(__FILE__), "onix", "other_text")
29
+ require File.join(File.dirname(__FILE__), "onix", "media_file")
30
+ require File.join(File.dirname(__FILE__), "onix", "imprint")
31
+ require File.join(File.dirname(__FILE__), "onix", "publisher")
32
+ require File.join(File.dirname(__FILE__), "onix", "sales_restriction")
33
+ require File.join(File.dirname(__FILE__), "onix", "stock")
34
+ require File.join(File.dirname(__FILE__), "onix", "price")
35
+ require File.join(File.dirname(__FILE__), "onix", "supply_detail")
36
+ require File.join(File.dirname(__FILE__), "onix", "product")
37
+ require File.join(File.dirname(__FILE__), "onix", "reader")
38
+ require File.join(File.dirname(__FILE__), "onix", "writer")
39
+
40
+ # lists
41
+ require File.join(File.dirname(__FILE__), "onix", "lists", "product_form")
42
+ require File.join(File.dirname(__FILE__), "onix", "lists", "product_availability")
43
+
44
+ # product wrappers
45
+ require File.join(File.dirname(__FILE__), "onix", "simple_product")
46
+ require File.join(File.dirname(__FILE__), "onix", "apa_product")
47
+
48
+ module ONIX
49
+ module Version #:nodoc:
50
+ Major = 0
51
+ Minor = 4
52
+ Tiny = 0
53
+
54
+ String = [Major, Minor, Tiny].join('.')
55
+ end
56
+
57
+ end
@@ -0,0 +1,9 @@
1
+ module ONIX
2
+ class AddresseeIdentifier
3
+ include ROXML
4
+
5
+ xml_accessor :addressee_id_type, :twodigit, :from => "AddresseeIDType"
6
+ xml_accessor :id_type_name, :from => "IDTypeName"
7
+ xml_accessor :id_value, :from => "IDValue"
8
+ end
9
+ end
@@ -0,0 +1,534 @@
1
+ module ONIX
2
+ class APAProduct < SimpleProduct
3
+
4
+ delegate :record_reference, :record_reference=
5
+ delegate :notification_type, :notification_type=
6
+ delegate :product_form, :product_form=
7
+ delegate :series, :series=
8
+ delegate :edition, :edition=
9
+ delegate :number_of_pages, :number_of_pages=
10
+ delegate :bic_main_subject, :bic_main_subject=
11
+ delegate :publishing_status, :publishing_status=
12
+ delegate :publication_date, :publication_date=
13
+
14
+ # retrieve the current EAN
15
+ def ean
16
+ identifier(3).andand.id_value
17
+ end
18
+
19
+ # set a new EAN
20
+ def ean=(isbn)
21
+ identifier_set(3, isbn)
22
+ end
23
+
24
+ # retrieve the proprietary ID
25
+ def proprietary_id
26
+ identifier(1).andand.id_value
27
+ end
28
+
29
+ # set a new proprietary ID
30
+ def proprietary_id=(isbn)
31
+ identifier_set(1, isbn)
32
+ end
33
+
34
+ # retrieve the current ISBN 10
35
+ def isbn10
36
+ identifier(2).andand.id_value
37
+ end
38
+
39
+ # set a new ISBN 10
40
+ def isbn10=(isbn)
41
+ identifier_set(2, isbn)
42
+ end
43
+
44
+ # retrieve the current ISBN 13
45
+ def isbn13
46
+ identifier(15).andand.id_value
47
+ end
48
+
49
+ # set a new ISBN 13
50
+ def isbn13=(isbn)
51
+ identifier_set(15, isbn)
52
+ end
53
+
54
+ # retrieve the current title
55
+ def title
56
+ composite = product.titles.first
57
+ if composite.nil?
58
+ nil
59
+ else
60
+ composite.title_text || composite.title_without_prefix
61
+ end
62
+ end
63
+
64
+ # set a new title
65
+ def title=(str)
66
+ composite = product.titles.first
67
+ if composite.nil?
68
+ composite = ONIX::Title.new
69
+ composite.title_type = 1
70
+ product.titles << composite
71
+ end
72
+ composite.title_text = str
73
+ end
74
+
75
+ # retrieve the current subtitle
76
+ def subtitle
77
+ composite = product.titles.first
78
+ if composite.nil?
79
+ nil
80
+ else
81
+ composite.subtitle
82
+ end
83
+ end
84
+
85
+ # set a new subtitle
86
+ def subtitle=(str)
87
+ composite = product.titles.first
88
+ if composite.nil?
89
+ composite = ONIX::Title.new
90
+ composite.title_type = 1
91
+ product.titles << composite
92
+ end
93
+ composite.subtitle = str
94
+ end
95
+
96
+ # retrieve the current publisher website for this particular product
97
+ def publisher_website
98
+ website(2).andand.website_link
99
+ end
100
+
101
+ # set a new publisher website for this particular product
102
+ def publisher_website=(str)
103
+ website_set(2, str)
104
+ end
105
+
106
+ # retrieve the current supplier website for this particular product
107
+ def supplier_website
108
+ website(12).andand.website_link
109
+ end
110
+
111
+ # set a new supplier website for this particular product
112
+ def supplier_website=(str)
113
+ website_set(12, str)
114
+ end
115
+
116
+ # retrieve an array of all contributors
117
+ def contributors
118
+ product.contributors.collect { |contrib| contrib.person_name_inverted || contrib.person_name}
119
+ end
120
+
121
+ # set a new contributor to this product
122
+ # str should be the contributors name inverted (Healy, James)
123
+ def add_contributor(str, role = "A01")
124
+ contrib = ::ONIX::Contributor.new
125
+ contrib.sequence_number = product.contributors.size + 1
126
+ contrib.contributor_role = role
127
+ contrib.person_name_inverted = str
128
+ product.contributors << contrib
129
+ end
130
+
131
+ # return an array of BIC subjects for this title
132
+ # could be version 1 or version 2, most ONIX files don't
133
+ # specifiy
134
+ def bic_subjects
135
+ subjects = product.subjects.select { |sub| sub.subject_scheme_id.to_i == 12 }
136
+ subjects.collect { |sub| sub.subject_code}
137
+ end
138
+
139
+ # add a BIC subject code to the product
140
+ def add_bic_subject(code)
141
+ add_subject code, "12"
142
+ end
143
+
144
+ # return an array of BISAC subjects for this title
145
+ def bisac_subjects
146
+ subjects = product.subjects.select { |sub| sub.subject_scheme_id.to_i == 10 }
147
+ subjects.collect { |sub| sub.subject_code}
148
+ end
149
+
150
+ # add a BISAC subject code to the product
151
+ def add_bisac_subject(code)
152
+ add_subject code, "10"
153
+ end
154
+
155
+ # retrieve the url to the product cover image
156
+ def cover_url
157
+ media_file(4).andand.media_file_link
158
+ end
159
+
160
+ # set the url to the product cover image
161
+ def cover_url=(url)
162
+ media_file_set(4,url)
163
+ end
164
+
165
+ # retrieve the url to the high quality product cover image
166
+ def cover_url_hq
167
+ media_file(6).andand.media_file_link
168
+ end
169
+
170
+ # set the url to the high quality product cover image
171
+ def cover_url_hq=(url)
172
+ media_file_set(6,url)
173
+ end
174
+
175
+ # retrieve the url to the product thumbnail
176
+ def thumbnail_url
177
+ media_file(7).andand.media_file_link
178
+ end
179
+
180
+ # set the url to the product cover image
181
+ def thumbnail_url=(url)
182
+ media_file_set(7,url)
183
+ end
184
+
185
+ # retrieve the main description
186
+ def main_description
187
+ other_text(1).andand.text
188
+ end
189
+
190
+ # set the main description
191
+ def main_description=(t)
192
+ other_text_set(1,t)
193
+ end
194
+
195
+ # retrieve the short description
196
+ def short_description
197
+ other_text(2).andand.text
198
+ end
199
+
200
+ # set the short description
201
+ def short_description=(t)
202
+ other_text_set(2,t)
203
+ end
204
+
205
+ # retrieve the long description
206
+ def long_description
207
+ other_text(3).andand.text
208
+ end
209
+
210
+ # set the long description
211
+ def long_description=(t)
212
+ other_text_set(3,t)
213
+ end
214
+
215
+ # retrieve the imprint
216
+ def imprint
217
+ composite = product.imprints.first
218
+ composite ? composite.imprint_name : nil
219
+ end
220
+
221
+ # set a new imprint
222
+ def imprint=(str)
223
+ composite = product.imprints.first
224
+ if composite.nil?
225
+ composite = ONIX::Imprint.new
226
+ product.imprints << composite
227
+ end
228
+ composite.imprint_name = str
229
+ end
230
+
231
+ # retrieve the publisher
232
+ def publisher
233
+ publisher_get(1).andand.publisher_name
234
+ end
235
+
236
+ # set a new publisher
237
+ def publisher=(str)
238
+ publisher_set(1, str)
239
+ end
240
+
241
+ # retrieve the sales restriction type
242
+ def sales_restriction_type
243
+ composite = product.sales_restrictions.first
244
+ composite.nil? ? nil : composite.imprint_name
245
+ end
246
+
247
+ # set a new sales restriction type
248
+ def sales_restriction_type=(type)
249
+ composite = product.sales_restrictions.first
250
+ if composite.nil?
251
+ composite = ONIX::SalesRestriction.new
252
+ product.sales_restrictions << composite
253
+ end
254
+ composite.sales_restriction_type = type
255
+ end
256
+
257
+ # retrieve the supplier name
258
+ def supplier_name
259
+ composite = product.supplier_details.first
260
+ composite.nil? ? nil : composite.supplier_name
261
+ end
262
+
263
+ # set a new supplier name
264
+ def supplier_name=(str)
265
+ composite = find_or_create_supply_detail
266
+ composite.supplier_name = str
267
+ end
268
+
269
+ # retrieve the supplier phone number
270
+ def supplier_phone
271
+ composite = product.supplier_details.first
272
+ composite.nil? ? nil : composite.telephone_number
273
+ end
274
+
275
+ # set a new supplier phone number
276
+ def supplier_phone=(str)
277
+ composite = find_or_create_supply_detail
278
+ composite.telephone_number = str
279
+ end
280
+
281
+ # retrieve the supplier fax number
282
+ def supplier_fax
283
+ composite = product.supplier_details.first
284
+ composite.nil? ? nil : composite.fax_number
285
+ end
286
+
287
+ # set a new supplier fax number
288
+ def supplier_fax=(str)
289
+ composite = find_or_create_supply_detail
290
+ composite.fax_number = str
291
+ end
292
+
293
+ # retrieve the supplier email address
294
+ def supplier_email
295
+ composite = product.supplier_details.first
296
+ composite.nil? ? nil : composite.email_address
297
+ end
298
+
299
+ # set a new supplier email address
300
+ def supplier_email=(str)
301
+ composite = find_or_create_supply_detail
302
+ composite.email_address = str
303
+ end
304
+
305
+ # retrieve the supply country code
306
+ def supply_country
307
+ composite = product.supplier_details.first
308
+ composite.nil? ? nil : composite.supply_to_country
309
+ end
310
+
311
+ # set a new supply country code
312
+ def supply_country=(str)
313
+ composite = find_or_create_supply_detail
314
+ composite.supply_to_country = str
315
+ end
316
+
317
+ # retrieve the product availability code
318
+ def product_availability
319
+ composite = product.supplier_details.first
320
+ composite.nil? ? nil : composite.product_availability
321
+ end
322
+
323
+ # set a new product availability
324
+ def product_availability=(num)
325
+ composite = find_or_create_supply_detail
326
+ composite.product_availability = num
327
+ end
328
+
329
+ # retrieve the number in stock
330
+ def on_hand
331
+ supply = find_or_create_supply_detail
332
+ composite = supply.stock.first
333
+ if composite.nil?
334
+ composite = ONIX::Stock.new
335
+ supply.stock << composite
336
+ end
337
+ composite.on_hand
338
+ end
339
+
340
+ # set a new in stock quantity
341
+ def on_hand=(num)
342
+ supply = find_or_create_supply_detail
343
+ composite = supply.stock.first
344
+ if composite.nil?
345
+ composite = ONIX::Stock.new
346
+ supply.stock << composite
347
+ end
348
+ composite.on_hand = num
349
+ end
350
+
351
+ # retrieve the number on order
352
+ def on_order
353
+ supply = find_or_create_supply_detail
354
+ composite = supply.stock.first
355
+ if composite.nil?
356
+ composite = ONIX::Stock.new
357
+ supply.stock << composite
358
+ end
359
+ composite.on_order
360
+ end
361
+
362
+ # set a new on order quantity
363
+ def on_order=(num)
364
+ supply = find_or_create_supply_detail
365
+ composite = supply.stock.first
366
+ if composite.nil?
367
+ composite = ONIX::Stock.new
368
+ supply.stock << composite
369
+ end
370
+ composite.on_order = num
371
+ end
372
+
373
+ # retrieve the rrp excluding any sales tax
374
+ def rrp_exc_sales_tax
375
+ price_get(1).andand.price_amount
376
+ end
377
+
378
+ # set the rrp excluding any sales tax
379
+ def rrp_exc_sales_tax=(num)
380
+ price_set(1, num)
381
+ end
382
+
383
+ # retrieve the rrp including any sales tax
384
+ def rrp_inc_sales_tax
385
+ price_get(2).andand.price_amount
386
+ end
387
+
388
+ # set the rrp including any sales tax
389
+ def rrp_inc_sales_tax=(num)
390
+ price_set(2, num)
391
+ end
392
+
393
+ private
394
+
395
+ # add a new subject to this product
396
+ # str should be the subject code
397
+ # type should be the code for the subject scheme you're using. See ONIX codelist 27.
398
+ # 12 is BIC
399
+ def add_subject(str, type = "12")
400
+ subject = ::ONIX::Subject.new
401
+ subject.subject_scheme_id = type.to_i
402
+ subject.subject_code = str
403
+ product.subjects << subject
404
+ end
405
+
406
+ def find_or_create_supply_detail
407
+ composite = product.supply_details.first
408
+ if composite.nil?
409
+ composite = ONIX::SupplyDetail.new
410
+ product.supply_details << composite
411
+ end
412
+ composite
413
+ end
414
+
415
+ # retrieve the value of a particular ID
416
+ def identifier(type)
417
+ product.product_identifiers.find { |id| id.product_id_type == type }
418
+ end
419
+
420
+ # set the value of a particular ID
421
+ def identifier_set(type, value)
422
+ isbn_id = identifier(type)
423
+
424
+ # create a new isbn record if we need to
425
+ if isbn_id.nil?
426
+ isbn_id = ONIX::ProductIdentifier.new
427
+ isbn_id.product_id_type = type
428
+ product.product_identifiers << isbn_id
429
+ end
430
+
431
+ isbn_id.id_value = value
432
+ end
433
+
434
+ # retrieve the value of a particular media file
435
+ def media_file(type)
436
+ product.media_files.find { |m| m.media_file_type_code == type }
437
+ end
438
+
439
+ # set the value of a particular ID
440
+ def media_file_set(type, value)
441
+ media = media_file(type)
442
+
443
+ # create a new isbn record if we need to
444
+ if media.nil?
445
+ media = ONIX::MediaFile.new
446
+ media.media_file_type_code = type
447
+ product.media_files << media
448
+ end
449
+
450
+ # store the new value
451
+ media.media_file_link = value.to_s
452
+ end
453
+
454
+ # retrieve the value of a particular price
455
+ def price_get(type)
456
+ supply = find_or_create_supply_detail
457
+ supply.prices.find { |p| p.price_type_code == type }
458
+ end
459
+
460
+ # set the value of a particular price
461
+ def price_set(type, num)
462
+ p = price_get(type)
463
+
464
+ # create a new isbn record if we need to
465
+ if p.nil?
466
+ supply = find_or_create_supply_detail
467
+ p = ONIX::Price.new
468
+ p.price_type_code = type
469
+ supply.prices << p
470
+ end
471
+
472
+ # store the new value
473
+ p.price_amount = num
474
+ end
475
+
476
+ # retrieve the value of a particular publisher
477
+ def publisher_get(type)
478
+ product.publishers.find { |pub| pub.publishing_role == type }
479
+ end
480
+
481
+ # set the value of a particular ID
482
+ def publisher_set(type, value)
483
+ pub = publisher_get(type)
484
+
485
+ # create a new isbn record if we need to
486
+ if pub.nil?
487
+ pub = ONIX::Publisher.new
488
+ pub.publishing_role = type
489
+ product.publishers << pub
490
+ end
491
+
492
+ # store the new value
493
+ pub.publisher_name = value.to_s
494
+ end
495
+
496
+ # retrieve the value of a particular other text value
497
+ def other_text(type)
498
+ product.text.find { |t| t.text_type_code == type }
499
+ end
500
+
501
+ # set the value of a particular other text value
502
+ def other_text_set(type, value)
503
+ text = other_text(type)
504
+
505
+ if text.nil?
506
+ text = ONIX::OtherText.new
507
+ text.text_type_code = type
508
+ self.text << text
509
+ end
510
+
511
+ # store the new value
512
+ text.text = value.to_s
513
+ end
514
+
515
+ # retrieve the value of a particular website
516
+ def website(type)
517
+ product.websites.find { |site| site.website_role == type }
518
+ end
519
+
520
+ # set the value of a particular website
521
+ def website_set(type, value)
522
+ site = website(type)
523
+
524
+ # create a new website record if we need to
525
+ if site.nil?
526
+ site = ONIX::Website.new
527
+ site.website_role = type
528
+ product.websites << site
529
+ end
530
+
531
+ site.website_link = value.to_s
532
+ end
533
+ end
534
+ end