im_onix 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/onix/subset.rb CHANGED
@@ -4,13 +4,13 @@ require 'cgi'
4
4
  module ONIX
5
5
  class ShortToRef
6
6
  def self.names
7
- @shortnames ||= YAML.load(File.open(File.dirname(__FILE__) + "/../../data/shortnames.yml"))
7
+ @shortnames ||= YAML.load(File.open(File.dirname(__FILE__) + "/../../data/shortnames.yml")).freeze
8
8
  end
9
9
  end
10
10
 
11
11
  class RefToShort
12
12
  def self.names
13
- @refnames ||= ShortToRef.names.invert
13
+ @refnames ||= ShortToRef.names.invert.freeze
14
14
  end
15
15
  end
16
16
 
@@ -25,6 +25,18 @@ module ONIX
25
25
  end
26
26
  end
27
27
 
28
+ # String only code-like class
29
+ class TextAttr
30
+ attr_accessor :code, :human
31
+
32
+ def self.from_code(code)
33
+ obj = self.new
34
+ obj.code = code
35
+ obj.human = code
36
+ obj
37
+ end
38
+ end
39
+
28
40
  module Attributes
29
41
  # @return [Hash<String,Code>]
30
42
  attr_accessor :attributes
@@ -44,16 +56,24 @@ module ONIX
44
56
  # @return [Class]
45
57
  def self.attribute_class(attr)
46
58
  case attr
47
- when "textcase"
48
- TextCase
49
- when "textformat"
50
- TextFormat
51
- when "language"
52
- LanguageCode
59
+ when "sourcename"
60
+ TextAttr
61
+ when "sourcetype"
62
+ RecordSourceType
63
+ when "collationkey"
64
+ TextAttr
53
65
  when "dateformat"
54
66
  DateFormat
55
67
  when "datestamp"
56
68
  DateStamp
69
+ when "language"
70
+ LanguageCode
71
+ when "textcase"
72
+ TextCase
73
+ when "textformat"
74
+ TextFormat
75
+ when "textscript"
76
+ ScriptCode
57
77
  else
58
78
  nil
59
79
  end
@@ -73,6 +93,7 @@ module ONIX
73
93
 
74
94
  # instanciate Subset form Nokogiri::XML::Element
75
95
  # @param [Nokogiri::XML::Element] n
96
+ # @return [Subset]
76
97
  def self.parse(n)
77
98
  o = self.new
78
99
  o.parse(n)
@@ -81,8 +102,11 @@ module ONIX
81
102
 
82
103
  # parse Nokogiri::XML::Element
83
104
  # @param [Nokogiri::XML::Element] n
105
+ # @return [void]
84
106
  def parse(n) end
85
107
 
108
+ # called when tag is not defined
109
+ # @param [String] tag
86
110
  def unsupported(tag)
87
111
  # raise SubsetUnsupported, [self.class, tag.name]
88
112
  # puts "WARN subset tag unsupported #{self.class}##{tag.name} (#{self.class.short_to_ref(tag.name)})"
@@ -91,10 +115,6 @@ module ONIX
91
115
  def tag_match(v)
92
116
  TagNameMatcher.new(v)
93
117
  end
94
-
95
- def self.tag_match(v)
96
- TagNameMatcher.new(v)
97
- end
98
118
  end
99
119
 
100
120
  # for class DSL
@@ -172,16 +192,9 @@ module ONIX
172
192
  @array
173
193
  end
174
194
 
175
- def _underscore_name
176
- if @array and @pluralize
177
- pluralize(underscore(@name))
178
- else
179
- underscore(@name)
180
- end
181
- end
182
-
195
+ # @return [String]
183
196
  def underscore_name
184
- @underscore_name ||= _underscore_name
197
+ @underscore_name ||= (@array && @pluralize) ? pluralize(underscore(@name)) : underscore(@name)
185
198
  end
186
199
 
187
200
  def class_name
@@ -216,6 +229,9 @@ module ONIX
216
229
  end
217
230
 
218
231
  class SubsetArray < Array
232
+ # @param [Symbol] k
233
+ # @param [String] p
234
+ # @return [SubsetArray]
219
235
  def human_code_match(k, p)
220
236
  case p
221
237
  when Regexp
@@ -236,6 +252,9 @@ module ONIX
236
252
  end
237
253
  end
238
254
 
255
+ # @param [Symbol] k
256
+ # @param [String] p
257
+ # @return [SubsetArray]
239
258
  def code_match(k, p)
240
259
  case p
241
260
  when Regexp
@@ -259,137 +278,155 @@ module ONIX
259
278
 
260
279
  # DSL
261
280
  class SubsetDSL < Subset
262
- def self.scope(name, lambda)
263
- @scopes ||= {}
264
- @scopes[name] = lambda
265
- end
281
+ class << self
282
+ # convert short name notation to reference
283
+ # @param [String] name
284
+ # @return [String]
285
+ def short_to_ref(name)
286
+ ShortToRef.names[name]
287
+ end
266
288
 
267
- def self._ancestor_registered_scopes
268
- els = self.registered_scopes
269
- sup = self
270
- while sup.respond_to?(:registered_scopes)
271
- els.merge!(sup.registered_scopes) if sup.registered_scopes
272
- sup = sup.superclass
289
+ # convert reference name notation to short
290
+ # @param [String] name
291
+ # @return [String]
292
+ def ref_to_short(name)
293
+ RefToShort.names[name]
273
294
  end
274
- els
275
- end
276
295
 
277
- def self.ancestor_registered_scopes
278
- @ancestors_registered_scopes ||= _ancestor_registered_scopes
279
- end
296
+ # infinity constant for cardinality
297
+ def n
298
+ Float::INFINITY
299
+ end
280
300
 
281
- def self.registered_scopes
282
- @scopes || {}
283
- end
301
+ # define a scope
302
+ # @param [Symbol] name
303
+ # @param [Lambda] lambda
304
+ # @return [void]
305
+ def scope(name, lambda)
306
+ @scopes ||= {}
307
+ @scopes[name] = lambda
308
+ end
284
309
 
285
- def self.element(name, type, options = {})
286
- @elements ||= {}
287
- @elements[name] = ElementParser.new(name, type, options)
288
- short_name = self.ref_to_short(name)
289
- if short_name
290
- @elements[short_name] = @elements[name].dup
291
- @elements[short_name].short = true
310
+ def registered_scopes
311
+ @scopes || {}
292
312
  end
293
313
 
294
- attr_accessor @elements[name].to_sym
314
+ def register_scopes(scopes)
315
+ @scopes ||= {}
316
+ @scopes = scopes.merge(@scopes)
317
+ end
295
318
 
296
- alias_method "#{@elements[name].underscore_name}_with_attributes".to_sym, @elements[name].to_sym
319
+ # define unique element
320
+ # @param [String] name
321
+ # @param [Symbol] type
322
+ # @param [Hash] options
323
+ # @return [void]
324
+ def element(name, type, options = {})
325
+ @elements ||= {}
326
+ @elements[name] = ElementParser.new(name, type, options)
327
+ short_name = self.ref_to_short(name)
328
+ if short_name
329
+ @elements[short_name] = @elements[name].dup
330
+ @elements[short_name].short = true
331
+ end
297
332
 
298
- current_element = @elements[name]
299
- define_method current_element.to_sym do |args = nil|
300
- val = instance_variable_get(current_element.to_instance)
301
- if val.respond_to?(:__getobj__)
302
- val.__getobj__
303
- else
304
- if val.is_a?(SubsetArray) and val.first and val.first.is_a?(TextWithAttributes)
305
- val.map{|v| v.respond_to?(:__getobj__) ? v.__getobj__ : v}
333
+ attr_accessor @elements[name].to_sym
334
+
335
+ alias_method "#{@elements[name].underscore_name}_with_attributes".to_sym, @elements[name].to_sym
336
+
337
+ current_element = @elements[name]
338
+ define_method current_element.to_sym do |args = nil|
339
+ val = instance_variable_get(current_element.to_instance)
340
+ if val.respond_to?(:__getobj__)
341
+ val.__getobj__
306
342
  else
307
- val
343
+ if val.is_a?(SubsetArray) and val.first and val.first.is_a?(TextWithAttributes)
344
+ val.map { |v| v.respond_to?(:__getobj__) ? v.__getobj__ : v }
345
+ else
346
+ val
347
+ end
308
348
  end
309
349
  end
350
+
351
+ if @elements[name].shortcut
352
+ current_element = @elements[name]
353
+ alias_method "#{current_element.shortcut.to_s}_with_attributes".to_sym, "#{@elements[name].underscore_name}_with_attributes".to_sym
354
+ alias_method current_element.shortcut, @elements[name].to_sym
355
+ end
356
+
357
+ @elements[name]
310
358
  end
311
359
 
312
- if @elements[name].shortcut
313
- current_element = @elements[name]
314
- alias_method "#{current_element.shortcut.to_s}_with_attributes".to_sym, "#{@elements[name].underscore_name}_with_attributes".to_sym
315
- alias_method current_element.shortcut, @elements[name].to_sym
360
+ # define multiple elements
361
+ # shortcut for element :array=>true
362
+ # @param [String] name
363
+ # @param [Symbol] type
364
+ # @param [Hash] options
365
+ # @return [void]
366
+ def elements(name, type, options = {})
367
+ self.element(name, type, options.merge(:array => true))
316
368
  end
317
- end
318
369
 
319
- # shortcut for element :array=>true
320
- def self.elements(name, type, options = {})
321
- self.element(name, type, options.merge(:array => true))
322
- end
370
+ # registered elements for this subset
371
+ # @return [Hash]
372
+ def registered_elements
373
+ @elements || {}
374
+ end
323
375
 
324
- def self._ancestors_registered_elements
325
- els = self.registered_elements
326
- sup = self
327
- while sup.respond_to?(:registered_elements)
328
- els.merge!(sup.registered_elements) if sup.registered_elements
329
- sup = sup.superclass
376
+ def register_elements(elements)
377
+ @elements ||= {}
378
+ @elements.merge!(elements)
330
379
  end
331
- els
332
- end
333
380
 
334
- def self.ancestors_registered_elements
335
- @ancestors_registered_elements ||= _ancestors_registered_elements
336
- end
381
+ def get_class(name)
382
+ ONIX.const_get(name) if ONIX.const_defined?(name)
383
+ end
337
384
 
338
- def self.registered_elements
339
- @elements || {}
385
+ def inherited(sublass)
386
+ sublass.register_scopes(self.registered_scopes)
387
+ sublass.register_elements(self.registered_elements)
388
+ end
340
389
  end
341
390
 
342
391
  def initialize
343
392
  # initialize plural as Array
344
- self.class.ancestors_registered_elements.each do |k, e|
393
+ self.registered_elements.values.each do |e|
345
394
  if e.is_array?
346
- # register a contextual SubsetArray object
347
- subset_array = SubsetArray.new
348
- subset_klass = self.class.get_class(e.class_name)
349
- if subset_klass.respond_to? :registered_scopes
350
- subset_klass.registered_scopes.each do |n, l|
351
- unless subset_array.respond_to? n.to_s
352
- subset_array.define_singleton_method(n.to_s) do
353
- instance_exec(&l)
354
- end
355
- end
356
- end
357
- end
358
- instance_variable_set(e.to_instance, subset_array)
395
+ register_subset_array(e)
359
396
  end
360
397
  end
361
398
  end
362
399
 
363
- def self.short_to_ref(name)
364
- ShortToRef.names[name]
365
- end
366
-
367
- def self.ref_to_short(name)
368
- RefToShort.names[name]
369
- end
370
-
371
- def self.get_class(name)
372
- ONIX.const_get(name) if ONIX.const_defined? name
373
- end
374
-
375
- # infinity constant for cardinality
376
- def self.n
377
- Float::INFINITY
400
+ def register_subset_array(e)
401
+ # register a contextual SubsetArray object
402
+ subset_array = SubsetArray.new
403
+ subset_klass = self.get_class(e.class_name)
404
+ if subset_klass.respond_to?(:registered_scopes)
405
+ subset_klass.registered_scopes.each do |n, l|
406
+ unless subset_array.respond_to?(n.to_s)
407
+ subset_array.define_singleton_method(n.to_s) do
408
+ instance_exec(&l)
409
+ end
410
+ end
411
+ end
412
+ end
413
+ instance_variable_set(e.to_instance, subset_array)
378
414
  end
379
415
 
380
- def get_registered_element(name)
381
- self.class.ancestors_registered_elements[name]
416
+ def registered_elements
417
+ self.class.registered_elements
382
418
  end
383
419
 
384
420
  def get_class(name)
385
421
  self.class.get_class(name)
386
422
  end
387
423
 
424
+ # @param [Nokogiri::XML::Element] n
425
+ # @return [void]
388
426
  def parse(n)
389
427
  parse_attributes(n.attributes)
390
428
  n.elements.each do |t|
391
- name = t.name
392
- e = self.get_registered_element(name)
429
+ e = self.registered_elements[t.name]
393
430
  if e
394
431
  primitive = true
395
432
  case e.type
@@ -429,7 +466,15 @@ module ONIX
429
466
  if val
430
467
  if primitive && t.attributes.length > 0
431
468
  if t.attributes["textformat"] && t.attributes["textformat"].to_s == "05" # content is XHTML
432
- val = CGI.unescapeHTML(t.children.map { |x| x.to_s }.join.strip)
469
+ xhtml = CGI.unescapeHTML(t.children.map { |x| x.to_s }.join.strip)
470
+ if Nokogiri::XML.parse(xhtml).root # check if val is really XHTML
471
+ val = xhtml
472
+ else
473
+ xhtml = CGI.unescapeHTML(val)
474
+ if Nokogiri::XML.parse(xhtml).root
475
+ val = xhtml
476
+ end
477
+ end
433
478
  end
434
479
  val = TextWithAttributes.new(val)
435
480
  val.parse(t.attributes)
@@ -441,7 +486,6 @@ module ONIX
441
486
  instance_variable_set(e.to_instance, e.parse_lambda(val))
442
487
  end
443
488
  end
444
-
445
489
  else
446
490
  unsupported(t)
447
491
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: im_onix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Boulnois
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-31 00:00:00.000000000 Z
11
+ date: 2022-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-prof
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: nokogiri
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -455,6 +483,7 @@ files:
455
483
  - lib/onix/ancillary_content.rb
456
484
  - lib/onix/audience.rb
457
485
  - lib/onix/audience_range.rb
486
+ - lib/onix/barcode.rb
458
487
  - lib/onix/builder.rb
459
488
  - lib/onix/cited_content.rb
460
489
  - lib/onix/code.rb
@@ -496,9 +525,10 @@ files:
496
525
  - lib/onix/product_contact.rb
497
526
  - lib/onix/product_form_feature.rb
498
527
  - lib/onix/product_part.rb
499
- - lib/onix/product_supplies_extractor.rb
528
+ - lib/onix/product_supplies_methods.rb
500
529
  - lib/onix/product_supply.rb
501
530
  - lib/onix/professional_affiliation.rb
531
+ - lib/onix/publisher_representative.rb
502
532
  - lib/onix/publishing_detail.rb
503
533
  - lib/onix/related_material.rb
504
534
  - lib/onix/related_product.rb