onix 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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