libis-metadata 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,46 +1,44 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'libis/tools/metadata/dublin_core_record'
3
+ require 'libis/metadata/dublin_core_record'
4
4
  require 'libis/tools/assert'
5
5
 
6
6
  module Libis
7
- module Tools
8
- module Metadata
9
- module Mappers
10
- # noinspection RubyResolve
7
+ module Metadata
8
+ module Mappers
9
+ # noinspection RubyResolve
11
10
 
12
- # Mixin for {::Libis::Tools::Metadata::DublinCoreRecord} to enable conversion of the Scope exported DC record.
13
- module Scope
11
+ # Mixin for {::Libis::Metadata::DublinCoreRecord} to enable conversion of the Scope exported DC record.
12
+ module Scope
14
13
 
15
- # Main conversion method.
16
- # @return [::Libis::Tools::Metadata::DublinCoreRecord]
17
- def to_dc
18
- assert(self.is_a? Libis::Tools::Metadata::DublinCoreRecord)
14
+ # Main conversion method.
15
+ # @return [::Libis::Metadata::DublinCoreRecord]
16
+ def to_dc
17
+ assert(self.is_a? Libis::Metadata::DublinCoreRecord)
19
18
 
20
- doc = Libis::Tools::Metadata::DublinCoreRecord.new(self.to_xml)
19
+ doc = Libis::Metadata::DublinCoreRecord.new(self.to_xml)
21
20
 
22
- if doc.isPartOf
21
+ if doc.isPartOf
23
22
 
24
- # create new node for isReferencedBy
25
- new_node = doc.add_node(
26
- 'isReferencedBy',
27
- doc.isPartOf.content,
28
- nil,
29
- 'xsi:type' => 'dcterms:URI'
30
- )
23
+ # create new node for isReferencedBy
24
+ new_node = doc.add_node(
25
+ 'isReferencedBy',
26
+ doc.isPartOf.content,
27
+ nil,
28
+ 'xsi:type' => 'dcterms:URI'
29
+ )
31
30
 
32
- # Replace isPartOf with isReferencedBy
33
- doc.isPartOf.replace new_node
34
-
35
- end
36
-
37
- doc
31
+ # Replace isPartOf with isReferencedBy
32
+ doc.isPartOf.replace new_node
38
33
 
39
34
  end
40
35
 
36
+ doc
37
+
41
38
  end
42
39
 
43
40
  end
41
+
44
42
  end
45
43
  end
46
- end
44
+ end
@@ -5,238 +5,236 @@ require 'libis/tools/assert'
5
5
  require_relative 'parser/subfield_criteria_parser'
6
6
 
7
7
  module Libis
8
- module Tools
9
- module Metadata
10
-
11
- # Helper class implementing a variable field for MARC
12
- class VarField
13
-
14
- attr_reader :tag
15
- attr_reader :ind1
16
- attr_reader :ind2
17
- attr_reader :subfield_data
18
-
19
- # Create new variable field with given tag and indicators
20
- # @param [String] tag tag
21
- # @param [String] ind1 first indicator. nil will be translated into empty string.
22
- # @param [String] ind2 second indicator. nil will be translated into empty string.
23
- def initialize(tag, ind1, ind2)
24
- @tag = tag
25
- @ind1 = ind1 || ''
26
- @ind2 = ind2 || ''
27
- @subfield_data = Hash.new { |h, k| h[k] = Array.new }
28
- end
8
+ module Metadata
9
+
10
+ # Helper class implementing a variable field for MARC
11
+ class VarField
12
+
13
+ attr_reader :tag
14
+ attr_reader :ind1
15
+ attr_reader :ind2
16
+ attr_reader :subfield_data
17
+
18
+ # Create new variable field with given tag and indicators
19
+ # @param [String] tag tag
20
+ # @param [String] ind1 first indicator. nil will be translated into empty string.
21
+ # @param [String] ind2 second indicator. nil will be translated into empty string.
22
+ def initialize(tag, ind1, ind2)
23
+ @tag = tag
24
+ @ind1 = ind1 || ''
25
+ @ind2 = ind2 || ''
26
+ @subfield_data = Hash.new {|h, k| h[k] = Array.new}
27
+ end
29
28
 
30
- # Add subfield to variable field
31
- # @param [String] name subfield indicator without '$'
32
- # @param [String] value content of the subfield
33
- def add_subfield(name, value)
34
- @subfield_data[name] << value
35
- end
29
+ # Add subfield to variable field
30
+ # @param [String] name subfield indicator without '$'
31
+ # @param [String] value content of the subfield
32
+ def add_subfield(name, value)
33
+ @subfield_data[name] << value
34
+ end
36
35
 
37
- # dump the contents
38
- #
39
- # @return [String] debug output to inspect the contents of the VarField
40
- def dump
41
- output = "#{@tag}:#{@ind1}:#{@ind2}:\n"
42
- @subfield_data.each { |s, t| output += "\t#{s}:#{t}\n" }
43
- output
44
- end
36
+ # dump the contents
37
+ #
38
+ # @return [String] debug output to inspect the contents of the VarField
39
+ def dump
40
+ output = "#{@tag}:#{@ind1}:#{@ind2}:\n"
41
+ @subfield_data.each {|s, t| output += "\t#{s}:#{t}\n"}
42
+ output
43
+ end
45
44
 
46
- # dump the contents
47
- #
48
- # @return [String] debug output to inspect the contents of the VarField - Single line version
49
- def dump_line
50
- output = "#{@tag}:#{@ind1}:#{@ind2}:"
51
- @subfield_data.each { |s, t| output += "$#{s}#{t}" }
52
- output
53
- end
45
+ # dump the contents
46
+ #
47
+ # @return [String] debug output to inspect the contents of the VarField - Single line version
48
+ def dump_line
49
+ output = "#{@tag}:#{@ind1}:#{@ind2}:"
50
+ @subfield_data.each {|s, t| output += "$#{s}#{t}"}
51
+ output
52
+ end
54
53
 
55
- # list the subfield codes
56
- #
57
- # @return [Array] a list of all subfield codes
58
- def keys
59
- @subfield_data.keys
60
- end
54
+ # list the subfield codes
55
+ #
56
+ # @return [Array] a list of all subfield codes
57
+ def keys
58
+ @subfield_data.keys
59
+ end
61
60
 
62
- # get the first (or only) subfield value for the given code
63
- #
64
- # @return [String] the first or only entry of a subfield or nil if not present
65
- # @param s [Character] the subfield code
66
- def subfield(s)
67
- subfield_array(s).first
68
- end
61
+ # get the first (or only) subfield value for the given code
62
+ #
63
+ # @return [String] the first or only entry of a subfield or nil if not present
64
+ # @param s [Character] the subfield code
65
+ def subfield(s)
66
+ subfield_array(s).first
67
+ end
69
68
 
70
- # get a list of all subfield values for a given code
71
- #
72
- # @return [Array] all the entries of a repeatable subfield
73
- # @param s [Character] the subfield code
74
- def subfield_array(s)
75
- assert(s.is_a?(String) && (s =~ /^[\da-z]$/) == 0, 'method expects a lower case alphanumerical char')
76
- @subfield_data.has_key?(s) ? @subfield_data[s].dup : []
77
- end
69
+ # get a list of all subfield values for a given code
70
+ #
71
+ # @return [Array] all the entries of a repeatable subfield
72
+ # @param s [Character] the subfield code
73
+ def subfield_array(s)
74
+ assert(s.is_a?(String) && (s =~ /^[\da-z]$/) == 0, 'method expects a lower case alphanumerical char')
75
+ @subfield_data.has_key?(s) ? @subfield_data[s].dup : []
76
+ end
78
77
 
79
- # get a list of the first subfield values for all the codes in the given string
80
- #
81
- # @return [Array] list of the first or only entries of all subfield codes in the input string
82
- # @param s [String] subfield code specification (see match)
83
- #
84
- # The subfield codes are cleaned (see criteria_to_array)
85
- def subfields(s)
86
- assert(s.is_a?(String), 'method expects a string')
87
- return [] unless (match_array = match(s))
88
- criteria_to_array(match_array.join(' ')).collect { |i| send(:subfield, i) }.flatten.compact
89
- end
78
+ # get a list of the first subfield values for all the codes in the given string
79
+ #
80
+ # @return [Array] list of the first or only entries of all subfield codes in the input string
81
+ # @param s [String] subfield code specification (see match)
82
+ #
83
+ # The subfield codes are cleaned (see criteria_to_array)
84
+ def subfields(s)
85
+ assert(s.is_a?(String), 'method expects a string')
86
+ return [] unless (match_array = match(s))
87
+ criteria_to_array(match_array.join(' ')).collect {|i| send(:subfield, i)}.flatten.compact
88
+ end
90
89
 
91
- # get a list of all the subfield values for all the codes in the given string
92
- #
93
- # @return [Array] list of the all the entries of all subfield codes in the input string
94
- # @param s [String] subfield code criteria (see match)
95
- #
96
- # The subfield codes are cleaned (see criteria_to_array)
97
-
98
- def subfields_array(s)
99
- assert(s.is_a?(String), 'method expects a string')
100
- return [] unless (match_array = match(s))
101
- criteria_to_array(match_array.join(' ')).collect { |i| send(:subfield_array, i) }.flatten.compact
102
- end
90
+ # get a list of all the subfield values for all the codes in the given string
91
+ #
92
+ # @return [Array] list of the all the entries of all subfield codes in the input string
93
+ # @param s [String] subfield code criteria (see match)
94
+ #
95
+ # The subfield codes are cleaned (see criteria_to_array)
96
+
97
+ def subfields_array(s)
98
+ assert(s.is_a?(String), 'method expects a string')
99
+ return [] unless (match_array = match(s))
100
+ criteria_to_array(match_array.join(' ')).collect {|i| send(:subfield_array, i)}.flatten.compact
101
+ end
103
102
 
104
- # check if the current VarField matches the given subfield criteria.
105
- #
106
- # @return [String] The matching part(s) of the criteria or nil if no match
107
- # @param criteria [String] subfield criteria: sequence of alternative set of subfield codes that should-shouldn't be present
108
- #
109
- # The subfield criteria consists of groups of characters. At least one of these groups should match for the test to succeed
110
- # Within the group sets of codes may be divided by a hyphen (-). The first set of codes must all be present;
111
- # the second set of codes must all <b>not</b> be present. Either set may be empty.
112
- #
113
- # Examples:
114
- # 'ab' matches '$a...$b...' => ['ab']
115
- # '$a...$b...$c...' => ['ab']
116
- # but not '$a...' => nil # ($b missing)
117
- # '$b...' => nil # ($a missing)
118
- # 'a b' matches '$a...' => ['a']
119
- # '$b...' => ['b']
120
- # '$a...$b...' => ['a', 'b']
121
- # '$a...$b...$c...' => ['a', 'b']
122
- # but not '$c...' => nil # ($a or $b must be present)
123
- # 'abc-d' matches '$a..,$b...$c...' => ['abc-d']
124
- # '$a..,$b...$c...$e...' => ['abc-d']
125
- # but not '$a...$b...$e...' => nil # ($c missing)
126
- # '$a...$b...$c...$d...' => nil # ($d should not be present)
127
- # 'a-b b-a' matches '$a...' => ['a-b']
128
- # '$a...$c...' => ['a-b']
129
- # '$b...' => ['b-a']
130
- # '$b...$c...' => ['b-a']
131
- # but not '$a...$b...' => nil
132
- # 'a-b c-d' matches '$a...' => ['a-b']
133
- # '$a...$c...' => ['a-b', 'c-d']
134
- # '$a...$b...$c...' => ['c-d']
135
- # '$b...$c...' => ['c-d']
136
- # but not '$a...$b...' => nil
137
- # '$c...$d...' => nil
138
- # '$b...$c...$d...' => nil
139
- # '$a...$b...$c...$d...' => nil
140
- def match(criteria)
141
- begin
142
- parser = Libis::Tools::Metadata::SubfieldCriteriaParser.new
143
- tree = parser.parse(criteria)
144
- return [] if tree.is_a? String
145
- tree = [tree] unless tree.is_a? Array
146
- result = tree.map do |selection|
147
- next unless parser.match_selection(selection, keys)
148
- parser.selection_to_s(selection)
149
- end.compact
150
- return nil if result.empty?
151
- result
152
- rescue Parslet::ParseFailed => failure
153
- failure.cause.set_label(criteria)
154
- raise failure
155
- end
103
+ # check if the current VarField matches the given subfield criteria.
104
+ #
105
+ # @return [String] The matching part(s) of the criteria or nil if no match
106
+ # @param criteria [String] subfield criteria: sequence of alternative set of subfield codes that should-shouldn't be present
107
+ #
108
+ # The subfield criteria consists of groups of characters. At least one of these groups should match for the test to succeed
109
+ # Within the group sets of codes may be divided by a hyphen (-). The first set of codes must all be present;
110
+ # the second set of codes must all <b>not</b> be present. Either set may be empty.
111
+ #
112
+ # Examples:
113
+ # 'ab' matches '$a...$b...' => ['ab']
114
+ # '$a...$b...$c...' => ['ab']
115
+ # but not '$a...' => nil # ($b missing)
116
+ # '$b...' => nil # ($a missing)
117
+ # 'a b' matches '$a...' => ['a']
118
+ # '$b...' => ['b']
119
+ # '$a...$b...' => ['a', 'b']
120
+ # '$a...$b...$c...' => ['a', 'b']
121
+ # but not '$c...' => nil # ($a or $b must be present)
122
+ # 'abc-d' matches '$a..,$b...$c...' => ['abc-d']
123
+ # '$a..,$b...$c...$e...' => ['abc-d']
124
+ # but not '$a...$b...$e...' => nil # ($c missing)
125
+ # '$a...$b...$c...$d...' => nil # ($d should not be present)
126
+ # 'a-b b-a' matches '$a...' => ['a-b']
127
+ # '$a...$c...' => ['a-b']
128
+ # '$b...' => ['b-a']
129
+ # '$b...$c...' => ['b-a']
130
+ # but not '$a...$b...' => nil
131
+ # 'a-b c-d' matches '$a...' => ['a-b']
132
+ # '$a...$c...' => ['a-b', 'c-d']
133
+ # '$a...$b...$c...' => ['c-d']
134
+ # '$b...$c...' => ['c-d']
135
+ # but not '$a...$b...' => nil
136
+ # '$c...$d...' => nil
137
+ # '$b...$c...$d...' => nil
138
+ # '$a...$b...$c...$d...' => nil
139
+ def match(criteria)
140
+ begin
141
+ parser = Libis::Metadata::Parser::SubfieldCriteriaParser.new
142
+ tree = parser.parse(criteria)
143
+ return [] if tree.is_a? String
144
+ tree = [tree] unless tree.is_a? Array
145
+ result = tree.map do |selection|
146
+ next unless parser.match_selection(selection, keys)
147
+ parser.selection_to_s(selection)
148
+ end.compact
149
+ return nil if result.empty?
150
+ result
151
+ rescue Parslet::ParseFailed => failure
152
+ failure.cause.set_label(criteria)
153
+ raise failure
156
154
  end
155
+ end
157
156
 
158
- private
157
+ private
159
158
 
160
- # @return [Array] cleaned up version of the input string
161
- # @param subfields [String] subfield code specification
162
- # cleans the subfield code specification and splits it into an array of characters
163
- # Duplicates will be removed from the array and the order will be untouched.
164
- def criteria_to_array(subfields)
159
+ # @return [Array] cleaned up version of the input string
160
+ # @param subfields [String] subfield code specification
161
+ # cleans the subfield code specification and splits it into an array of characters
162
+ # Duplicates will be removed from the array and the order will be untouched.
163
+ def criteria_to_array(subfields)
165
164
 
166
- # note that we remove the '-xxx' part as it is only required for matching
167
- subfields.gsub(/ |-\w*/, '').split('').uniq
168
- end
165
+ # note that we remove the '-xxx' part as it is only required for matching
166
+ subfields.gsub(/ |-\w*/, '').split('').uniq
167
+ end
169
168
 
170
- def sort_helper(x)
171
- # make sure that everything below 'A' is higher than 'z'
172
- # note that this only works for numbers, but that is fine in our case.
173
- x < 'A' ? (x.to_i + 123).chr : x
174
- end
169
+ def sort_helper(x)
170
+ # make sure that everything below 'A' is higher than 'z'
171
+ # note that this only works for numbers, but that is fine in our case.
172
+ x < 'A' ? (x.to_i + 123).chr : x
173
+ end
175
174
 
176
- # implementation for methods for retrieving subfield values
177
- #
178
- # The methods start with a single character: the operation
179
- # 'f' for retrieving only the first occurence of the subfield
180
- # 'a' for retrieving all the subfield values for each of the given subfields
181
- # if omitted, 'f' is assumed
182
- #
183
- # Then a '_' acts as a subdivider between the operation and the subfield(s). It must always be present, even
184
- # if the operation is omitted.
185
- #
186
- # The last past is a sequence of subfield codes that should be used for selecting the values. The order in which the
187
- # subfields are listed is respected in the resulting array of values.
188
- #
189
- # Examples:
190
- #
191
- # t = VarField.new('100', '', '',
192
- # { 'a' => %w'Name NickName',
193
- # 'b' => %w'LastName MaidenName',
194
- # 'c' => %w'eMail',
195
- # '1' => %w'Age',
196
- # '9' => %w'Score'})
197
- #
198
- # # >> 100##$aName$aNickName$bLastName$bMaidenName$ceMail$1Age$9Score <<
199
- #
200
- # t._1ab => ['Age', 'Name', 'LastName']
201
- # # equivalent to: t.f_1av or t.fields('1ab')
202
- #
203
- # t.a_9ab => ['Score', 'Name', 'NickName', 'LastName', 'MaidenName']
204
- # # equivalent to: t.fields_array('9ab')
205
- #
206
- # Note that it is not possible to use a fieldspec for the sequence of subfield codes. Spaces and '-' are not allowed
207
- # in method calls. If you want this, use the #subfield(s) and #subfield(s)_array methods.
208
- #
209
- def method_missing(name, *args)
210
- operation, subfields = name.to_s.split('_')
211
- assert(subfields.size > 0, 'need to specify at least one subfield')
212
- operation = 'f' if operation.empty?
213
- # convert subfield list to fieldspec
214
- subfields = subfields.split('').join(' ')
215
- case operation
216
- when 'f'
217
- if subfields.size > 1
218
- operation = :subfields
219
- else
220
- operation = :subfield
221
- end
222
- when 'a'
223
- if subfields.size > 1
224
- operation = :subfields_array
225
- else
226
- operation = :subfield_array
227
- end
228
- else
229
- throw "Unknown method invocation: '#{name}' with: #{args}"
175
+ # implementation for methods for retrieving subfield values
176
+ #
177
+ # The methods start with a single character: the operation
178
+ # 'f' for retrieving only the first occurence of the subfield
179
+ # 'a' for retrieving all the subfield values for each of the given subfields
180
+ # if omitted, 'f' is assumed
181
+ #
182
+ # Then a '_' acts as a subdivider between the operation and the subfield(s). It must always be present, even
183
+ # if the operation is omitted.
184
+ #
185
+ # The last past is a sequence of subfield codes that should be used for selecting the values. The order in which the
186
+ # subfields are listed is respected in the resulting array of values.
187
+ #
188
+ # Examples:
189
+ #
190
+ # t = VarField.new('100', '', '',
191
+ # { 'a' => %w'Name NickName',
192
+ # 'b' => %w'LastName MaidenName',
193
+ # 'c' => %w'eMail',
194
+ # '1' => %w'Age',
195
+ # '9' => %w'Score'})
196
+ #
197
+ # # >> 100##$aName$aNickName$bLastName$bMaidenName$ceMail$1Age$9Score <<
198
+ #
199
+ # t._1ab => ['Age', 'Name', 'LastName']
200
+ # # equivalent to: t.f_1av or t.fields('1ab')
201
+ #
202
+ # t.a_9ab => ['Score', 'Name', 'NickName', 'LastName', 'MaidenName']
203
+ # # equivalent to: t.fields_array('9ab')
204
+ #
205
+ # Note that it is not possible to use a fieldspec for the sequence of subfield codes. Spaces and '-' are not allowed
206
+ # in method calls. If you want this, use the #subfield(s) and #subfield(s)_array methods.
207
+ #
208
+ def method_missing(name, *args)
209
+ operation, subfields = name.to_s.split('_')
210
+ assert(subfields.size > 0, 'need to specify at least one subfield')
211
+ operation = 'f' if operation.empty?
212
+ # convert subfield list to fieldspec
213
+ subfields = subfields.split('').join(' ')
214
+ case operation
215
+ when 'f'
216
+ if subfields.size > 1
217
+ operation = :subfields
218
+ else
219
+ operation = :subfield
230
220
  end
231
- send(operation, subfields)
232
- end
233
-
234
- def to_ary
235
- nil
221
+ when 'a'
222
+ if subfields.size > 1
223
+ operation = :subfields_array
224
+ else
225
+ operation = :subfield_array
226
+ end
227
+ else
228
+ throw "Unknown method invocation: '#{name}' with: #{args}"
236
229
  end
230
+ send(operation, subfields)
231
+ end
237
232
 
233
+ def to_ary
234
+ nil
238
235
  end
239
236
 
240
237
  end
238
+
241
239
  end
242
- end
240
+ end