marc4j4r 0.2.2 → 0.2.4

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/README.markdown ADDED
@@ -0,0 +1,128 @@
1
+ # marc4j4r
2
+
3
+ A ruby wrapper around the marc4j.jar (as forked by javamarc) java library for dealing with library MARC data.
4
+
5
+ ## Getting a MARC reader
6
+
7
+ marc4j4r provides three readers out of the box: :strictmarc (binary), :permissivemarc (:binary), and :marcxml (MARC-XML).
8
+ You can pass either a filename or an open IO object (either ruby or java.io.inputstream)
9
+
10
+ require 'marc4j4r'
11
+
12
+ binreader = MARC4J4R::Reader.new('test.mrc') # defaults to :strictmarc
13
+ binreader = MARC4J4R::Reader.new('test.mrc', :strictmarc)
14
+
15
+ permissivereader = MARC4J4R::Reader.new('test.mrc', :permissivemarc)
16
+
17
+ xmlreader = MARC4J4R::Reader.new('test.xml', :marcxml)
18
+
19
+ # Or use a file object
20
+
21
+ reader = MARC4J4R::Reader.new(File.open('test.mrc'))
22
+
23
+ # Or a java.io.inputstream
24
+
25
+ jurl = Java::java.net.URL.new('http://my.machine.com/test.mrc')
26
+ istream = jurl.openConnection.getInputStream
27
+ reader = MARC4J4R::Reader.new(istream)
28
+
29
+ ## Using the reader
30
+
31
+ A MARC4J4R::Reader is an Enumerable, so you can do:
32
+
33
+ reader.each do |record|
34
+ # do stuff with the record
35
+ end
36
+
37
+ Or, if you're using [threach](http://rdoc.info/projects/billdueber/threach):
38
+
39
+ reader.threach(2) do |record|
40
+ # do stuff with records in two threads
41
+ end
42
+
43
+ ## Using the writer
44
+
45
+ The writer code has not yet been tested; it *should* work as follows:
46
+
47
+ binaryWriter = MARC4J4R::Writer.new(filename, :strictmarc)
48
+ xmlWriter = MARC4J4R::Writer.new(filename, :marcxml)
49
+
50
+ writer.write(record)
51
+ # repeat
52
+ writer.close
53
+
54
+
55
+ ## Working with records and fields
56
+
57
+ In addition to all the normal marc4j methods, MARC4J4R::Record exposes some additional methods
58
+ and syntaxes.
59
+
60
+ **See the classes themselves and/or the specs for more examples.**
61
+
62
+ leader = record.leader
63
+
64
+ # All fields are available via #each or #fields
65
+
66
+ fields = record.fields
67
+
68
+ record.each do |field|
69
+ # do something with each controlfield/datafield; returned in the order they were added
70
+ end
71
+
72
+ # Controlfields have a tag and a value
73
+
74
+ idfield = record['001']
75
+ idfield.tag # => '001'
76
+ id = idfield.value # or idfield.data, same thing
77
+
78
+ # Get the first datafield with a given tag
79
+ first700 = record['700'] # Note: need to use strings, not integers
80
+
81
+ # Stringify a field to get all the subfields joined with spaces
82
+
83
+ fullTitle = record['245'].to_s
84
+
85
+ all700s = record.find_by_tag '700'
86
+ all700and856s = record.find_by_tag ['700', '856']
87
+
88
+
89
+ # Construct and add a controlfield
90
+ record << MARC4J4R::ControlField.new('001', '0000333234')
91
+
92
+ # Construct and add a datafield
93
+ df = MARC4J4R::DataField.new(tag, ind1, ind2)
94
+
95
+ ind1 = df.ind1
96
+ ind2 = df.ind2
97
+
98
+ df << MARC4J4R::Subfield.new('a', 'the $a value')
99
+ df << MARC4J4R::Subfield.new('b', 'the $b value')
100
+
101
+ # Add it to a record
102
+
103
+ record << df
104
+
105
+ # Get subfields or their values
106
+
107
+ firstSubfieldAValue = df['a']
108
+
109
+ allSubfields = df.subs
110
+ allSubfieldAs = df.subs('a')
111
+ allSubfieldAorBs = df.subs(['a', 'b'])
112
+
113
+ allSubfieldAorBValues = df.sub_values(['a', 'b'])
114
+
115
+
116
+ ## Note on Patches/Pull Requests
117
+
118
+ * Fork the project.
119
+ * Make your feature addition or bug fix.
120
+ * Add tests for it. This is important so I don't break it in a
121
+ future version unintentionally.
122
+ * Commit, do not mess with rakefile, version, or history.
123
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
124
+ * Send me a pull request. Bonus points for topic branches.
125
+
126
+ ## Copyright
127
+
128
+ Copyright (c) 2010 BillDueber. See LICENSE for details.
data/Rakefile CHANGED
@@ -13,6 +13,7 @@ begin
13
13
  gem.authors = ["BillDueber"]
14
14
  gem.add_development_dependency "bacon", ">= 0"
15
15
  gem.add_development_dependency "yard", ">= 0"
16
+
16
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
18
  end
18
19
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.2
1
+ 0.2.4
@@ -95,7 +95,7 @@ module MARC4J4R
95
95
  code = [code]
96
96
  end
97
97
 
98
- return self.grep {|s| code.include? s.code}
98
+ return self.select {|s| code.include? s.code}
99
99
  end
100
100
 
101
101
  # Get all values from the subfields for the given code or array of codes
@@ -110,7 +110,7 @@ module MARC4J4R
110
110
  # rec['260'].sub_values(['a', 'c']) #=> ["New York,", "1969"]
111
111
  # rec['260'].sub_values(['c', 'a']) #=> ["New York,", "1969"]
112
112
 
113
- def sub_values(code)
113
+ def sub_values(code=nil)
114
114
  return self.subs(code).collect {|s| s.value}
115
115
  end
116
116
 
metadata CHANGED
@@ -1,46 +1,51 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marc4j4r
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 31
4
5
  prerelease: false
5
6
  segments:
6
- - 0
7
- - 2
8
- - 2
9
- version: 0.2.2
7
+ - 0
8
+ - 2
9
+ - 4
10
+ version: 0.2.4
10
11
  platform: ruby
11
12
  authors:
12
- - BillDueber
13
+ - BillDueber
13
14
  autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-07-13 00:00:00 -04:00
18
+ date: 2010-07-23 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: bacon
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
30
- type: :development
31
- version_requirements: *id001
32
- - !ruby/object:Gem::Dependency
33
- name: yard
34
- prerelease: false
35
- requirement: &id002 !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- segments:
40
- - 0
41
- version: "0"
42
- type: :development
43
- version_requirements: *id002
21
+ - !ruby/object:Gem::Dependency
22
+ name: bacon
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
44
49
  description: Syntactic sugar and some extra methods to deal with MARC data using the java .jar marc4j
45
50
  email: bill@dueber.com
46
51
  executables: []
@@ -50,56 +55,59 @@ extensions: []
50
55
  extra_rdoc_files: []
51
56
 
52
57
  files:
53
- - LICENSE
54
- - README.rdoc
55
- - Rakefile
56
- - VERSION
57
- - jars/marc4j.jar
58
- - lib/marc4j4r.rb
59
- - lib/marc4j4r/controlfield.rb
60
- - lib/marc4j4r/datafield.rb
61
- - lib/marc4j4r/reader.rb
62
- - lib/marc4j4r/record.rb
63
- - lib/marc4j4r/writer.rb
64
- - lib/original_monolithic_file.rb
65
- - spec/batch.dat
66
- - spec/batch.txt
67
- - spec/batch.xml
68
- - spec/controlfield_spec.rb
69
- - spec/datafield_spec.rb
70
- - spec/one.dat
71
- - spec/one.txt
72
- - spec/one.xml
73
- - spec/reader_spec.rb
74
- - spec/record_spec.rb
75
- - spec/spec_helper.rb
58
+ - LICENSE
59
+ - README.markdown
60
+ - Rakefile
61
+ - VERSION
62
+ - jars/marc4j.jar
63
+ - lib/marc4j4r.rb
64
+ - lib/marc4j4r/controlfield.rb
65
+ - lib/marc4j4r/datafield.rb
66
+ - lib/marc4j4r/reader.rb
67
+ - lib/marc4j4r/record.rb
68
+ - lib/marc4j4r/writer.rb
69
+ - spec/batch.dat
70
+ - spec/batch.txt
71
+ - spec/batch.xml
72
+ - spec/controlfield_spec.rb
73
+ - spec/datafield_spec.rb
74
+ - spec/one.dat
75
+ - spec/one.txt
76
+ - spec/one.xml
77
+ - spec/reader_spec.rb
78
+ - spec/record_spec.rb
79
+ - spec/spec_helper.rb
76
80
  has_rdoc: true
77
81
  homepage: http://github.com/billdueber/javamarc/tree/master/ruby/marc4j4r/
78
82
  licenses: []
79
83
 
80
84
  post_install_message:
81
85
  rdoc_options:
82
- - --charset=UTF-8
86
+ - --charset=UTF-8
83
87
  require_paths:
84
- - lib
88
+ - lib
85
89
  required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
86
91
  requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- segments:
90
- - 0
91
- version: "0"
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
92
98
  required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
93
100
  requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- segments:
97
- - 0
98
- version: "0"
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
106
+ version: "0"
99
107
  requirements: []
100
108
 
101
109
  rubyforge_project:
102
- rubygems_version: 1.3.6
110
+ rubygems_version: 1.3.7
103
111
  signing_key:
104
112
  specification_version: 3
105
113
  summary: Use marc4j java library in JRuby in a more ruby-ish way
data/README.rdoc DELETED
@@ -1,17 +0,0 @@
1
- = marc4j4r
2
-
3
- Description goes here.
4
-
5
- == Note on Patches/Pull Requests
6
-
7
- * Fork the project.
8
- * Make your feature addition or bug fix.
9
- * Add tests for it. This is important so I don't break it in a
10
- future version unintentionally.
11
- * Commit, do not mess with rakefile, version, or history.
12
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
- * Send me a pull request. Bonus points for topic branches.
14
-
15
- == Copyright
16
-
17
- Copyright (c) 2010 BillDueber. See LICENSE for details.
@@ -1,518 +0,0 @@
1
- unless defined? JRUBY_VERSION
2
- raise "Only works under JRUBY"
3
- end
4
-
5
- begin
6
- include_class Java::org.marc4j.marc.impl.RecordImpl
7
- rescue NameError => e
8
- jardir = File.join(File.dirname(__FILE__), '..', 'jars')
9
- require "#{jardir}/marc4j.jar"
10
- end
11
-
12
- require 'set'
13
-
14
-
15
- # Re-open the MarcReader interface, define #each and include Enumerable
16
- #
17
- # We also automatically call #hashify on the records that stream through
18
- # #each in order to speed up RecordImpl#[] when (a) doing many operations on a single
19
- # record, and (b) we're not worried about interleaved tags (e.g., a 520 followed by a 510 followed
20
- # by another 520)
21
-
22
- module Java::OrgMarc4j::MarcReader
23
- include Enumerable
24
-
25
- # Return the next record, after calling #hashify on it
26
- def each(hashify=true)
27
- while self.hasNext
28
- r = self.next
29
- r.hashify if hashify
30
- yield r
31
- end
32
- end
33
- end
34
-
35
-
36
- module MARC4J4R
37
-
38
- # Do some simple substitutions to make things prettier. After this,
39
- # we can use MARC4J4R::Record instead of Java::org.marc4j.marc.impl::RecordImpl
40
-
41
- Record = Java::org.marc4j.marc.impl::RecordImpl
42
- ControlField = Java::org.marc4j.marc.impl::ControlFieldImpl
43
- DataField = Java::org.marc4j.marc.impl::DataFieldImpl
44
- SubField = Java::org.marc4j.marc.impl::SubfieldImpl
45
-
46
-
47
- # Add some sugar to the MarcReader interface
48
- #
49
- # Adjust the interface so that a #new call to any implementations that
50
- # implement it can take a java.io.InputStream, ruby IO obejct, or String
51
- # (that will be interpreted as a filename) without complaining.
52
- #
53
- # The mechanism -- running module_eval on a string-representation of the
54
- # new method in each of the hard-coded implementations of MarcReader
55
- # (MarcStreamReader,MarcPermissiveStreamReader,MarcXmlReader) -- is ugly
56
- # and deeply unsettling.
57
- #
58
- # @author Bill Dueber
59
- #
60
- # A string used to override the initializer for each stream reader
61
- # Need to do it this ugly way because of the way java and ruby interact;
62
- # can't just add it to the MarcReader interface the way I wanted to.
63
-
64
- NEWINIT = <<-ENDBINDER
65
- include Enumerable
66
- alias_method :oldinit, :initialize
67
- def initialize(fromwhere)
68
- stream = nil
69
- if fromwhere.is_a? Java::JavaIO::InputStream or fromwhere.is_a? Java::JavaIO::ByteArrayInputStream
70
- stream = fromwhere
71
- elsif fromwhere.is_a? IO
72
- stream = fromwhere.to_inputstream
73
- else
74
- stream = java.io.FileInputStream.new(fromwhere.to_java_string)
75
- end
76
- if self.class == Java::org.marc4j.MarcPermissiveStreamReader
77
- self.oldinit(stream, true, true)
78
- else
79
- self.oldinit(stream)
80
- end
81
- end
82
- ENDBINDER
83
-
84
- Java::org.marc4j.MarcStreamReader.module_eval(NEWINIT)
85
- Java::org.marc4j.MarcPermissiveStreamReader.module_eval(NEWINIT)
86
- Java::org.marc4j.MarcXmlReader.module_eval(NEWINIT)
87
-
88
-
89
-
90
- # Get a marc reader of the appropriate type
91
- # @param [String, IO, java.io.InputStream] input The IO stream (or filename) from which you want to read
92
- # @param [:strictmarc, :permissivemarc, :marcxml] The type of MARC reader you want.
93
- # @return [MarcReader] A MarcReader object with the syntactic sugar added in this file (e.g, each)
94
- #
95
- # @example Get a strict binary MARC reader for the file 'test.mrc'
96
- # reader = MARC4J4R.reader('test.mrc')
97
- #
98
- # @example Get a permissive binary MARC reader
99
- # reader = MARC4J4R.reader('test.mrc', :permissivemarc)
100
- #
101
- # @example Get a reader for an xml file
102
- # reader = MARC4J4R.reader('test.xml', :marcxml)
103
- #
104
- # @example Get a reader based on an existing IO object
105
- # require 'open-uri'
106
- # infile = open('http://my.machine.com/test.mrc')
107
- # reader = MARC4J4R.reader(infile)
108
-
109
- def reader(input, type = :strictmarc)
110
- case type
111
- when :strictmarc then
112
- return Java::org.marc4j.MarcStreamReader.new(input)
113
- when :permissivemarc then
114
- return Java::org.marc4j.MarcPermissiveStreamReader.new(input)
115
- when :marcxml then
116
- return Java::org.marc4j.MarcXmlReader.new(input)
117
- when :alephsequential then
118
- return MARC4J4R::AlephSequentialReader.new(input)
119
- else
120
- raise ArgumentError, "Reader type #{type} illegal: must be :strictmarc, :permissivemarc, :marcxml, or :alephsequential"
121
- end
122
- end
123
- module_function :reader
124
-
125
-
126
- # Implement an AlephSequential reader
127
- class AlephSequentialReader
128
- include Enumerable
129
- def initialize(fromwhere)
130
- stream = nil
131
- if fromwhere.is_a? Java::JavaIO::InputStream
132
- stream = fromwhere.to_io
133
- elsif fromwhere.is_a? IO
134
- stream = fromwhere
135
- else
136
- stream = File.new(fromwhere)
137
- end
138
-
139
- @handle = stream
140
- end
141
-
142
- def each
143
- record = nil
144
- currentID = nil
145
-
146
- @handle.each_line do |l|
147
- l.chomp!
148
- next unless l =~ /\S/
149
- vals = l.unpack('a9 a a3 c c a3 a*')
150
- id, tag, ind1, ind2, data = vals[0], vals[2], vals[3], vals[4], vals[6]
151
- # id, tag, ind1, ind2, junk, data = *(l.unpack('A10 a3 c c a3 A*'))
152
- if id != currentID
153
- if record
154
- yield record
155
- end
156
- record = RecordImpl.new
157
- currentID = id
158
- end
159
- if tag == 'LDR'
160
- record.setLeader(Java::org.marc4j.marc.impl.LeaderImpl.new(data))
161
- else
162
- record << buildField(tag,ind1,ind2,data)
163
- end
164
- end
165
- yield record
166
- end
167
-
168
-
169
- SUBREGEXP = /\$\$(.)/
170
- def buildField (tag, ind1, ind2, data)
171
- if Java::org.marc4j.marc.impl.Verifier.isControlField tag
172
- return Java::org.marc4j.marc.impl.ControlFieldImpl.new(tag, data)
173
- else
174
- f = Java::org.marc4j.marc.impl.DataFieldImpl.new(tag, ind1, ind2)
175
- data.split(SUBREGEXP)[1..-1].each_slice(2) do |code, value|
176
- f.addSubfield Java::org.marc4j.marc.impl.SubfieldImpl.new(code[0].ord, value)
177
- end
178
- return f
179
- end
180
- end
181
-
182
- end # End of class AlephSequentialReader
183
-
184
- end
185
-
186
-
187
- # Open up RecordImpl to add some sugar, including Enumberable as well
188
- # @author Bill Dueber
189
-
190
- class Record
191
- include Enumerable
192
-
193
- alias_method :<<, :addVariableField
194
- alias_method :append, :addVariableField
195
- alias_method :fields, :getVariableFields
196
-
197
- # Export as a MARC-Hash, as described at
198
- # http://robotlibrarian.billdueber.com/marc-hash-the-saga-continues-now-with-even-less-structure/
199
- # @return A marc-hash representation of the record, suitable for calling .to_json on or whatever
200
- def to_marchash
201
- h = {}
202
- h['type'] = 'marc-hash'
203
- h['version'] = [1,0]
204
- h['leader'] = self.leader
205
-
206
- fields = []
207
-
208
- self.getVariableFields.each do |f|
209
- if f.controlField?
210
- fields << [f.tag, f.value]
211
- else
212
- farray = [f.tag, f.indicator1 || ' ', f.indicator2 || ' ']
213
- subs = []
214
- f.each do |subfield|
215
- subs << [subfield.code, subfield.value]
216
- end
217
- farray.push subs
218
- fields << farray
219
- end
220
- end
221
- h['fields'] = fields
222
- return h
223
- end
224
-
225
- # Create a local hash by tag number; makes some stuff faster
226
- # Called automatically if you use reader.each
227
-
228
- def hashify
229
- return if @hashedtags # don't do it more than once
230
- @hashedtags = {}
231
- self.getVariableFields.each do |f|
232
- @hashedtags[f.tag] ||= []
233
- @hashedtags[f.tag].push f
234
- end
235
- end
236
-
237
- # Create a nice string of the record
238
- def to_s
239
- arr = ['LEADER ' + self.leader]
240
- self.each do |f|
241
- arr.push f.to_s
242
- end
243
- return arr.join("\n")
244
- end
245
-
246
- # Get the leader as a string (marc4j would otherwise return Leader object)
247
- def leader
248
- self.get_leader.toString
249
- end
250
-
251
-
252
- # Cycle through the fields in the order the appear in the record
253
- def each
254
- self.getVariableFields.each do |f|
255
- yield f
256
- end
257
- end
258
-
259
- # Get the first field associated with a tag
260
- # @param [String] tag The tag
261
- # @return [Field] The first matching field, or nil if none. Note that
262
- # to mirror ruby-marc, this returns a single field
263
-
264
- def [] tag
265
- if defined? @hashedtags
266
- if @hashedtags[tag]
267
- return @hashedtags[tag][0]
268
- else
269
- return nil
270
- end
271
- else
272
- return self.getVariableField(tag)
273
- end
274
- end
275
-
276
-
277
- # Get a (possibly empty) list of fields with the given tag(s)
278
- #
279
- # @param [String, Array<String>] tags A string (or Array of strings) with the tags you're interested in
280
- # @param [Boolean] originalorder Whether or not results should be presented in the original order within the
281
- # record or with a two-column sort of (a) Order of the tag in the list of tags sent, (b) order within that tag
282
- # in the record
283
- # @return [Array<Field>] Either an empty list or a list of one or more matched fields will be returned.
284
- #
285
- # originalorder == false will use an internal hash and be faster in many cases (see #hashify)
286
- #
287
- # @example originalorder == false
288
- # # Given a record that looks like
289
- # # 010 $a 68027371
290
- # # 035 $a (RLIN)MIUG0001728-B
291
- # # 035 $a (CaOTULAS)159818044
292
- # # 035 $a (OCoLC)ocm00001728
293
- #
294
- # r.find_by_tag(['035', '010']).each {|f| puts f.to_s}
295
- # # 035 $a (RLIN)MIUG0001728-B
296
- # # 035 $a (CaOTULAS)159818044
297
- # # 035 $a (OCoLC)ocm00001728
298
- # # 010 $a 68027371
299
- #
300
- # # The results are ordered first by tag as passed in, then by original order within the tag
301
- #
302
- # @example Just get all fields for a single tag
303
- # ohThirtyFives = r.find_by_tag('035')
304
- #
305
- # @example Get a bunch of standard identifiers
306
- # standardIDs = r.find_by_tag(['022', '020', '010'])
307
- #
308
- # @example originalorder == true
309
- # r.find_by_tag(['035', '010'], true).each {|f| puts f.to_s}
310
- # # 010 $a 68027371
311
- # # 035 $a (RLIN)MIUG0001728-B
312
- # # 035 $a (CaOTULAS)159818044
313
- # # 035 $a (OCoLC)ocm00001728
314
-
315
- def find_by_tag(tags, originalorder = false)
316
- self.hashify unless @hashedtags and !originalorder
317
- if !tags.is_a? Array
318
- return @hashedtags[tags] || []
319
- end
320
- if originalorder
321
- return self.find_all {|f| tags.include? f.tag}
322
- else
323
- # puts "Tags is #{tags}: got #{@hashedtags.values_at(*tags)}"
324
- return @hashedtags.values_at(*tags).flatten.compact
325
- end
326
- end
327
-
328
-
329
-
330
- # Return the record as valid MARC-XML
331
- # @return String A MARC-XML representation of the record, including the XML header
332
- def to_xml
333
- return @xml if @xml
334
- begin
335
- @xml = java.io.StringWriter.new
336
- res = javax.xml.transform.stream.StreamResult.new(@xml)
337
- writer = org.marc4j.MarcXmlWriter.new(res)
338
- writer.write(self)
339
- writer.writeEndDocument
340
- return @xml.toString
341
- rescue
342
- "Woops! to_xml failed for record #{self['001'].data}: #{$!}"
343
- end
344
- end
345
-
346
- def to_marc
347
- begin
348
- s = Java::java.io.ByteArrayOutputStream.new
349
- writer = org.marc4j.MarcStreamWriter.new(s)
350
- writer.write(self)
351
- @marcbinary = s.to_string
352
- puts @marcbinary
353
- return @marcbinary
354
- rescue
355
- # "Woops! to_marc failed for record #{self['001'].data}: #{$!}"
356
- "Whoops! Failed: #{$!}"
357
- end
358
- end
359
-
360
-
361
- end
362
-
363
- class ControlField
364
- def value
365
- return self.data
366
- end
367
-
368
- def controlField?
369
- return true
370
- end
371
-
372
- def self.control_tag? tag
373
- return Java::org.marc4j.marc.impl.Verifier.isControlField tag
374
- end
375
-
376
- # Pretty-print
377
- # @param [String] joiner What string to use to join the subfields
378
- # @param [String] The pretty string
379
- def to_s
380
- return self.tag + " " + self.value
381
- end
382
-
383
- def == other
384
- self.tag == other.tag && self.value == other.value
385
- end
386
-
387
- end
388
-
389
- class DataField
390
- include Enumerable
391
-
392
- alias_method :<<, :addSubfield
393
-
394
-
395
- def controlField?
396
- return false
397
- end
398
-
399
- # Broken. Need to check subs as well
400
- def == other
401
- self.tag == other.tag and
402
- self.indicator1 == other.indicator1 and
403
- self.indicator2 == other.indicator2
404
- end
405
-
406
- # Pretty-print
407
- # @param [String] joiner What string to use to join the subfields
408
- # @param [String] The pretty string
409
- def to_s (joiner = ' ')
410
- arr = [self.tag + ' ' + self.indicator1 + self.indicator2]
411
- self.each do |s|
412
- arr.push s.to_s
413
- end
414
- return arr.join(joiner)
415
- end
416
-
417
- # Get the value of the first subfield of this field with the given code
418
- # @param [String] code 1-character string of the subfield code
419
- # @return [String] The value of the first matched subfield
420
- def [] code
421
- raise ArgumentError, "Code must be a one-character string, not #{code}" unless code.is_a? String and code.size == 1
422
- # need to send a char value that the underlying java can deal with
423
- sub = self.getSubfield(code[0].ord)
424
- if (sub)
425
- return sub.getData
426
- else
427
- return nil
428
- end
429
- end
430
-
431
-
432
- # Get all values from the subfields for the given code or array of codes
433
- # @param [String, Array<String>] code (Array of?) 1-character string(s) of the subfield code
434
- # @param [Boolean] myorder Use the order of subfields that I gave instead of the order they're in the record
435
- # @return [Array<String>] A possibly-empty array of Strings made up of the values in the subfields whose
436
- # code is included in the given codes. If myorder == true, use the order in which they are passed in; if a code is repeated
437
- # (ocassionally legal) subfield values will appear first ordered by the passed array, then by order within
438
- # the document.
439
- #
440
- # If myorder is false, just return the values for matching subfields in the order they appear in the field.
441
- #
442
- # @example Quick examples:
443
- # # 260 $a New York, $b Van Nostrand Reinhold Co. $c 1969
444
- # rec['260'].sub_values('a') #=> ["New York,"]
445
- # rec['260'].sub_values(['a', 'c']) #=> ["New York,", "1969"]
446
- # rec['260'].sub_values(['c', 'a']) #=> ["New York,", "1969"]
447
- # rec['260'].sub_values(['c', 'a'], true) #=> ["1969", "New York"]
448
-
449
- def sub_values(code, myorder = false)
450
-
451
- # Do a little razzle-dazzle for the common case when a single code is given
452
- if not [Set, Array].include? code.class
453
- c = code
454
- elsif code.size == 1
455
- c = code.first
456
- end
457
- if c
458
- return self.find_all { |s| c == s.code}.map {|s| s.data}
459
- end
460
-
461
- # unless [Set, Array].include? code.class
462
- # code = [code]
463
- # # puts "Arrayified for code #{code} / #{code.class}"
464
- # end
465
- if myorder
466
- subs = []
467
- code.each do |c|
468
- subs << self.find_all {|s| c == s.code}
469
- end
470
- return subs.flatten.map {|s| s.data}
471
- else
472
- return self.find_all{|s| code.include? s.code}.map {|s| s.data}
473
- end
474
- end
475
-
476
- # Get first indicator as a one-character string
477
- def indicator1
478
- return self.getIndicator1.chr
479
- end
480
-
481
- # Get second indicator as a one-character string
482
- def indicator2
483
- return self.getIndicator2.chr
484
- end
485
-
486
- # Iterate over the subfields
487
- def each
488
- self.getSubfields.each do |s|
489
- yield s
490
- end
491
- end
492
-
493
- # Get the concatentated values of the subfields in order the appear in the field
494
- # @param [String] joiner The string used to join the subfield values
495
- def value joiner=' '
496
- data = self.getSubfields.map {|s| s.data}
497
- return data.join(joiner)
498
- end
499
- end
500
-
501
- class SubField
502
-
503
- def == other
504
- return ((self.code == other.code) and (self.data == other.data))
505
- end
506
-
507
- def value
508
- return self.data
509
- end
510
-
511
- def code
512
- return self.getCode.chr
513
- end
514
-
515
- def to_s
516
- return '$' + self.code + " " + self.data
517
- end
518
- end