milkfarm-onix 0.7.7 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG +31 -1
  2. data/README.markdown +24 -2
  3. data/lib/onix.rb +3 -16
  4. data/lib/onix/addressee_identifier.rb +0 -1
  5. data/lib/onix/apa_product.rb +19 -2
  6. data/lib/onix/audience_range.rb +6 -7
  7. data/lib/onix/contributor.rb +0 -1
  8. data/lib/onix/header.rb +0 -1
  9. data/lib/onix/imprint.rb +0 -1
  10. data/lib/onix/language.rb +0 -1
  11. data/lib/onix/lists/contributor_role.rb +99 -0
  12. data/lib/onix/market_representation.rb +0 -1
  13. data/lib/onix/measure.rb +0 -1
  14. data/lib/onix/media_file.rb +0 -1
  15. data/lib/onix/normaliser.rb +0 -77
  16. data/lib/onix/other_text.rb +0 -1
  17. data/lib/onix/price.rb +0 -1
  18. data/lib/onix/product.rb +3 -2
  19. data/lib/onix/product_identifier.rb +0 -1
  20. data/lib/onix/publisher.rb +0 -1
  21. data/lib/onix/reader.rb +39 -96
  22. data/lib/onix/sales_restriction.rb +0 -1
  23. data/lib/onix/sender_identifier.rb +0 -1
  24. data/lib/onix/series.rb +8 -8
  25. data/lib/onix/series_identifier.rb +0 -1
  26. data/lib/onix/set.rb +76 -0
  27. data/lib/onix/sl_product.rb +32 -45
  28. data/lib/onix/stock.rb +0 -1
  29. data/lib/onix/subject.rb +0 -1
  30. data/lib/onix/supply_detail.rb +0 -1
  31. data/lib/onix/title.rb +0 -1
  32. data/lib/onix/website.rb +0 -1
  33. data/lib/onix/writer.rb +1 -1
  34. data/spec/apa_product_spec.rb +44 -4
  35. data/spec/audience_range_spec.rb +5 -7
  36. data/spec/contributor_spec.rb +2 -4
  37. data/spec/header_spec.rb +2 -4
  38. data/spec/imprint_spec.rb +4 -6
  39. data/spec/language_spec.rb +5 -7
  40. data/spec/market_representation_spec.rb +2 -4
  41. data/spec/measure_spec.rb +2 -4
  42. data/spec/media_file_spec.rb +2 -4
  43. data/spec/normaliser_spec.rb +1 -78
  44. data/spec/other_text_spec.rb +2 -4
  45. data/spec/price_spec.rb +2 -4
  46. data/spec/product_identifier_spec.rb +2 -4
  47. data/spec/product_spec.rb +2 -5
  48. data/spec/publisher_spec.rb +2 -4
  49. data/spec/reader_spec.rb +15 -22
  50. data/spec/sales_restriction_spec.rb +2 -4
  51. data/spec/sender_identifier.rb +2 -4
  52. data/spec/series_identifier_spec.rb +5 -7
  53. data/spec/series_spec.rb +4 -6
  54. data/spec/set_spec.rb +32 -0
  55. data/spec/sl_product_spec.rb +76 -24
  56. data/spec/spec_helper.rb +8 -0
  57. data/spec/stock_spec.rb +2 -4
  58. data/spec/subject_spec.rb +2 -4
  59. data/spec/supply_detail_spec.rb +2 -4
  60. data/spec/title_spec.rb +2 -4
  61. data/spec/website_spec.rb +2 -4
  62. data/spec/writer_spec.rb +1 -4
  63. metadata +64 -28
  64. data/lib/onix/common.rb +0 -26
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class OtherText
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "OtherText"
9
8
 
data/lib/onix/price.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class Price
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "Price"
9
8
 
data/lib/onix/product.rb CHANGED
@@ -3,16 +3,16 @@
3
3
  module ONIX
4
4
  class Product
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "Product"
9
-
8
+
10
9
  xml_accessor :record_reference, :from => "RecordReference"
11
10
  xml_accessor :notification_type, :from => "NotificationType", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
12
11
  xml_accessor :product_identifiers, :from => "ProductIdentifier", :as => [ONIX::ProductIdentifier]
13
12
  xml_accessor :product_form, :from => "ProductForm"
14
13
  xml_accessor :product_form_detail, :from => "ProductFormDetail"
15
14
  xml_accessor :series, :from => "Series", :as => [ONIX::Series]
15
+ xml_accessor :sets, :from => "Set", :as => [ONIX::Set]
16
16
  xml_accessor :titles, :from => "Title", :as => [ONIX::Title]
17
17
  xml_accessor :websites, :from => "Website", :as => [ONIX::Website]
18
18
  xml_accessor :contributors, :from => "Contributor", :as => [ONIX::Contributor]
@@ -54,6 +54,7 @@ module ONIX
54
54
  def initialize
55
55
  self.product_identifiers = []
56
56
  self.series = []
57
+ self.sets = []
57
58
  self.titles = []
58
59
  self.contributors = []
59
60
  self.websites = []
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class ProductIdentifier
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "ProductIdentifier"
9
8
 
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class Publisher
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "Publisher"
9
8
 
data/lib/onix/reader.rb CHANGED
@@ -53,31 +53,39 @@ module ONIX
53
53
  class Reader
54
54
  include Enumerable
55
55
 
56
- attr_reader :header , :version, :xml_lang, :xml_version, :encoding
56
+ attr_reader :header, :release
57
57
 
58
58
  def initialize(input, product_klass = ::ONIX::Product)
59
59
  if input.kind_of?(String)
60
- @reader = LibXML::XML::Reader.file(input)
60
+ @file = File.open(input, "r")
61
+ @reader = Nokogiri::XML::Reader(@file) { |cfg| cfg.dtdload.noent }
61
62
  elsif input.kind_of?(IO)
62
- @reader = LibXML::XML::Reader.io(input)
63
+ @reader = Nokogiri::XML::Reader(input) { |cfg| cfg.dtdload.noent }
63
64
  else
64
65
  raise ArgumentError, "Unable to read from file or IO stream"
65
66
  end
66
67
 
67
68
  @product_klass = product_klass
68
69
 
69
- @header = read_next
70
+ @release = find_release
71
+ @header = find_header
70
72
 
71
- @xml_lang ||= @reader.xml_lang
73
+ @xml_lang ||= @reader.lang
72
74
  @xml_version ||= @reader.xml_version.to_f
73
- @encoding ||= encoding_const_to_name(@reader.encoding)
74
75
  end
75
76
 
76
77
  # Iterate over all the products in an ONIX file
77
78
  #
78
79
  def each(&block)
79
- while obj = read_next
80
- yield obj
80
+ @reader.each do |node|
81
+ if @reader.node_type == 1 && @reader.name == "Product"
82
+ str = @reader.outer_xml
83
+ if str.nil?
84
+ yield @product_klass.new
85
+ else
86
+ yield @product_klass.from_xml(str)
87
+ end
88
+ end
81
89
  end
82
90
  end
83
91
 
@@ -87,101 +95,36 @@ module ONIX
87
95
 
88
96
  private
89
97
 
90
- # Walk the ONIX file, and grab the next header or product fragment.
91
- #
92
- def read_next
93
- while @reader.read
94
-
95
- if @reader.node_type == LibXML::XML::Reader::TYPE_DOCUMENT_TYPE
96
- # TODO restore ONIX version extraction. The following expand()
97
- # call is triggering unpredictable behaviour in libxml-ruby
98
- # 1.1.3 with libxml2 2.7.3. Sometimes segfaults, othertimes
99
- # cryptic errors about the input file being truncated or
100
- # incomplete
101
- #uri = @reader.expand.to_s.dup
102
- #m, major, minor, rev = *uri.match(/.+(\d)\.(\d)\/(\d*).*/)
103
- #@version = [major.to_i, minor.to_i, rev.to_i]
104
- elsif @reader.node_type == LibXML::XML::Reader::TYPE_ELEMENT
105
- if @reader.name == "Header"
106
- str = normalise_string_encoding(@reader.read_outer_xml.to_s.dup)
107
- if str.size == 0
108
- return ONIX::Header.new
109
- else
110
- return ONIX::Header.from_xml(str)
111
- end
112
- elsif @reader.name == "Product"
113
- str = normalise_string_encoding(@reader.read_outer_xml.to_s.dup)
114
- if str.size == 0
115
- return @product_klass.new
116
- else
117
- return @product_klass.from_xml(str)
118
- end
98
+ def find_release
99
+ 2.times do
100
+ @reader.read
101
+ if @reader.node_type == 1 && @reader.name == "ONIXMessage"
102
+ value = @reader.attributes["release"]
103
+ if value
104
+ return BigDecimal.new(value)
105
+ else
106
+ return nil
119
107
  end
108
+ elsif @reader.node_type == 14
109
+ return nil
120
110
  end
121
111
  end
122
-
123
- return nil
124
- rescue LibXML::XML::Error => e
125
112
  return nil
126
113
  end
127
114
 
128
- # XML::Reader seems to transparently convert all input data to utf-8, howver
129
- # on Ruby 1.9 it fails to correctly set the encoding on the strings.
130
- #
131
- def normalise_string_encoding(str)
132
- if RUBY_VERSION >= "1.9"
133
- return str.dup.force_encoding("utf-8")
134
- else
135
- str
136
- end
137
- end
138
-
139
- # simple mapping of encoding constants to a string
140
- #
141
- def encoding_const_to_name(const)
142
- return nil if const.nil?
143
- case const
144
- when LibXML::XML::Encoding::UTF_8
145
- "utf-8"
146
- when LibXML::XML::Encoding::UTF_16LE
147
- "utf-16le"
148
- when LibXML::XML::Encoding::UTF_16BE
149
- "utf-16be"
150
- when LibXML::XML::Encoding::UCS_4LE
151
- "ucs-4le"
152
- when LibXML::XML::Encoding::UCS_4BE
153
- "ucs-4be"
154
- when LibXML::XML::Encoding::UCS_2
155
- "ucs-2"
156
- when LibXML::XML::Encoding::ISO_8859_1
157
- "iso-8859-1"
158
- when LibXML::XML::Encoding::ISO_8859_2
159
- "iso-8859-2"
160
- when LibXML::XML::Encoding::ISO_8859_3
161
- "iso-8859-3"
162
- when LibXML::XML::Encoding::ISO_8859_4
163
- "iso-8859-4"
164
- when LibXML::XML::Encoding::ISO_8859_5
165
- "iso-8859-5"
166
- when LibXML::XML::Encoding::ISO_8859_6
167
- "iso-8859-6"
168
- when LibXML::XML::Encoding::ISO_8859_7
169
- "iso-8859-7"
170
- when LibXML::XML::Encoding::ISO_8859_8
171
- "iso-8859-8"
172
- when LibXML::XML::Encoding::ISO_8859_9
173
- "iso-8859-9"
174
- when LibXML::XML::Encoding::ISO_2022_JP
175
- "iso-2022-jp"
176
- when LibXML::XML::Encoding::SHIFT_JIS
177
- "shift-jis"
178
- when LibXML::XML::Encoding::EUC_JP
179
- "euc-jp"
180
- when LibXML::XML::Encoding::ASCII
181
- "ascii"
182
- else
183
- nil
115
+ def find_header
116
+ 100.times do
117
+ @reader.read
118
+ if @reader.node_type == 1 && @reader.name == "Header"
119
+ str = @reader.outer_xml
120
+ if str.nil?
121
+ return ONIX::Header.new
122
+ else
123
+ return ONIX::Header.from_xml(str)
124
+ end
125
+ end
184
126
  end
127
+ return nil
185
128
  end
186
129
  end
187
130
  end
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class SalesRestriction
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "SalesRestriction"
9
8
 
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class SenderIdentifier
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "SenderIdentifier"
9
8
 
data/lib/onix/series.rb CHANGED
@@ -3,17 +3,16 @@
3
3
  module ONIX
4
4
  class Series
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "Series"
9
8
 
10
9
  xml_accessor :series_identifiers, :from => "SeriesIdentifier", :as => [ONIX::SeriesIdentifier]
11
10
  xml_accessor :title_of_series, :from => "TitleOfSeries"
12
-
11
+
13
12
  def initialize
14
13
  self.series_identifiers = []
15
14
  end
16
-
15
+
17
16
  # retrieve the proprietary series ID
18
17
  def proprietary_series_id
19
18
  series_identifier(1).andand.id_value
@@ -23,7 +22,7 @@ module ONIX
23
22
  def proprietary_series_id=(id)
24
23
  series_identifier_set(1, id)
25
24
  end
26
-
25
+
27
26
  # retrieve the issn
28
27
  def issn
29
28
  series_identifier(2).andand.id_value
@@ -33,7 +32,7 @@ module ONIX
33
32
  def issn=(id)
34
33
  series_identifier_set(2, id)
35
34
  end
36
-
35
+
37
36
  # retrieve the value of a particular ID
38
37
  def series_identifier(type)
39
38
  identifier = series_identifiers.find { |id| id.series_id_type == type }
@@ -42,16 +41,17 @@ module ONIX
42
41
  # set the value of a particular ID
43
42
  def series_identifier_set(type, value)
44
43
  series_indentifier_id = series_identifiers.find { |id| id.series_id_type == type }
45
-
44
+
46
45
  # create a new series identifier record if we need to
47
46
  if series_indentifier_id.nil?
48
47
  series_indentifier_id = ONIX::SeriesIdentifier.new
49
48
  end
50
-
49
+
51
50
  series_indentifier_id.series_id_type = type
52
51
  series_indentifier_id.id_value = value
53
-
52
+
54
53
  series_identifiers << series_indentifier_id
55
54
  end
55
+
56
56
  end
57
57
  end
@@ -3,7 +3,6 @@
3
3
  module ONIX
4
4
  class SeriesIdentifier
5
5
  include ROXML
6
- include ONIX::Common
7
6
 
8
7
  xml_name "SeriesIdentifier"
9
8
 
data/lib/onix/set.rb ADDED
@@ -0,0 +1,76 @@
1
+ # coding: utf-8
2
+
3
+ module ONIX
4
+ class Set
5
+ include ROXML
6
+
7
+ xml_name "Set"
8
+
9
+ xml_accessor :product_identifiers, :from => "ProductIdentifier", :as => [ONIX::ProductIdentifier]
10
+ xml_accessor :title_of_set, :from => "TitleOfSet"
11
+
12
+ def initialize
13
+ self.product_identifiers = []
14
+ end
15
+
16
+ # retrieve the proprietary set ID
17
+ def proprietary_set_id
18
+ product_identifier(1).andand.id_value
19
+ end
20
+
21
+ # set a new proprietary set ID
22
+ def proprietary_set_id=(id)
23
+ product_identifier_set(1, id)
24
+ end
25
+
26
+ # retrieve the 10-digit isbn
27
+ def isbn10
28
+ product_identifier(2).andand.id_value
29
+ end
30
+
31
+ # set a new 10-digit isbn
32
+ def isbn10=(id)
33
+ product_identifier_set(2, id)
34
+ end
35
+
36
+ # retrieve the 13-digit isbn
37
+ def isbn
38
+ product_identifier(15).andand.id_value
39
+ end
40
+
41
+ # set a new 13-digit isbn
42
+ def isbn=(id)
43
+ product_identifier_set(15, id)
44
+ end
45
+
46
+ # retrieve the lccn
47
+ def lccn
48
+ product_identifier(13).andand.id_value
49
+ end
50
+
51
+ # set a new lccn
52
+ def lccn=(id)
53
+ product_identifier_set(13, id)
54
+ end
55
+
56
+ # retrieve the value of a particular ID
57
+ def product_identifier(type)
58
+ identifier = product_identifiers.find { |id| id.product_id_type == type }
59
+ end
60
+
61
+ # set the value of a particular ID
62
+ def product_identifier_set(type, value)
63
+ product_identifier_id = product_identifiers.find { |id| id.product_id_type == type }
64
+
65
+ # create a new set identifier record if we need to
66
+ if product_identifier_id.nil?
67
+ product_identifier_id = ONIX::ProductIdentifier.new
68
+ end
69
+
70
+ product_identifier_id.product_id_type = type
71
+ product_identifier_id.id_value = value
72
+
73
+ product_identifiers << product_identifier_id
74
+ end
75
+ end
76
+ end
@@ -2,18 +2,11 @@
2
2
 
3
3
  module ONIX
4
4
  class SLProduct < APAProduct
5
-
5
+
6
6
  delegate :audience_code, :audience_code=
7
7
  delegate :copyright_year, :copyright_year=
8
8
  delegate :product_form_detail, :product_form_detail=
9
9
 
10
- alias_method :old_initialize, :initialize
11
- def initialize(*args)
12
- result = old_initialize(*args)
13
- result.audience_code = 4 # Primary & secondary/elementary & high school
14
- result
15
- end
16
-
17
10
  # retrieve the value of a particular ID
18
11
  def series(str)
19
12
  product.series.find { |id| id.title_of_series == str }
@@ -36,47 +29,41 @@ module ONIX
36
29
  end
37
30
  end
38
31
 
39
- # retrieve the "language of text" (role=1) language code for this particular product
40
- def language_code
41
- language(1).andand.language_code
42
- end
43
-
44
- # set a new "language of text" (role=1) language code for this particular product
45
- def language_code=(str)
46
- language_set(1, str)
47
- end
48
-
49
- # retrieve the "language of text" (role=1) country code for this particular product
50
- def country_code
51
- language(1).andand.country_code
32
+ # retrieve the value of a particular ID
33
+ def set(str)
34
+ product.sets.find { |id| id.title_of_set == str }
52
35
  end
53
36
 
54
- # set a new "language of text" (role=1) country code for this particular product
55
- def country_code=(str)
56
- language_set(1, language_code, str)
37
+ # set the value of a particular ID
38
+ def set=(value)
39
+ # process based on value type
40
+ if value.is_a?(Set)
41
+ str = value.title_of_set
42
+ set_id = value
43
+ else
44
+ str = value
45
+ set_id = ONIX::Set.new
46
+ set_id.title_of_set = value
47
+ end
48
+ # check if exists already
49
+ unless set(str)
50
+ product.sets << set_id
51
+ end
57
52
  end
58
53
 
59
- # retrieve the value of a particular language
60
- def language(type)
61
- product.languages.find { |l| l.language_role == type }
54
+ # retrieve an array of all languages
55
+ def languages
56
+ product.languages.collect { |language| language.language_code}
62
57
  end
63
58
 
64
- # set the value of a particular language
65
- def language_set(type, value, value2=nil)
66
- l = language(type)
67
-
68
- # create a new language record if we need to
69
- if l.nil?
70
- l = ONIX::Language.new
71
- l.language_role = type
72
- product.languages << l
73
- end
74
-
75
- # cannot set country_code without language_code
76
- unless value.nil?
77
- l.language_code = value.to_s # mandatory
78
- l.country_code = value2.to_s if value2 # optional
79
- end
59
+ # set a new language to this product
60
+ # str should be the languages name code (US)
61
+ def add_language(str, role = "1", country = "US")
62
+ language = ::ONIX::Language.new
63
+ language.language_role = role
64
+ language.language_code = str
65
+ language.country_code = country
66
+ product.languages << language
80
67
  end
81
68
 
82
69
  # retrieve the dewey for this title
@@ -99,7 +86,7 @@ module ONIX
99
86
  def us_grade_range=(range=[])
100
87
  audience_range_set(11, range[0], range[1])
101
88
  end
102
-
89
+
103
90
  # retrieve the value of a particular audience range
104
91
  def audience_range(type)
105
92
  product.audience_ranges.find { |a| a.audience_range_qualifier == type }
@@ -126,6 +113,6 @@ module ONIX
126
113
  end
127
114
  a.audience_range_precisions = ["01"] if min.nil? || max.nil?
128
115
  end
129
-
116
+
130
117
  end
131
118
  end