marc4j4r 0.1.6 → 0.2.2
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.rdoc +17 -0
- data/Rakefile +26 -13
- data/VERSION +1 -1
- data/jars/marc4j.jar +0 -0
- data/lib/marc4j4r/controlfield.rb +32 -0
- data/lib/marc4j4r/datafield.rb +196 -0
- data/lib/marc4j4r/reader.rb +71 -0
- data/lib/marc4j4r/record.rb +214 -0
- data/lib/marc4j4r/writer.rb +29 -0
- data/lib/marc4j4r.rb +26 -485
- data/lib/original_monolithic_file.rb +518 -0
- data/spec/batch.dat +1 -0
- data/spec/batch.txt +193 -0
- data/spec/batch.xml +13 -0
- data/spec/controlfield_spec.rb +40 -0
- data/spec/datafield_spec.rb +56 -0
- data/spec/one.dat +1 -0
- data/spec/one.txt +17 -0
- data/spec/one.xml +4 -0
- data/spec/reader_spec.rb +49 -0
- data/spec/record_spec.rb +101 -0
- data/{test/helper.rb → spec/spec_helper.rb} +9 -5
- metadata +74 -80
- data/.document +0 -5
- data/.gitignore +0 -21
- data/README.markdown +0 -41
- data/doc/ControlFieldImpl.html +0 -314
- data/doc/DataFieldImpl.html +0 -875
- data/doc/Java/OrgMarc4j/MarcReader.html +0 -184
- data/doc/MARC4J4R/Reader.html +0 -245
- data/doc/MARC4J4R.html +0 -281
- data/doc/RecordImpl.html +0 -686
- data/doc/SubfieldImpl.html +0 -252
- data/doc/_index.html +0 -153
- data/doc/class_list.html +0 -36
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -50
- data/doc/css/style.css +0 -268
- data/doc/file.README.html +0 -90
- data/doc/file_list.html +0 -38
- data/doc/frames.html +0 -13
- data/doc/index.html +0 -90
- data/doc/js/app.js +0 -99
- data/doc/js/full_list.js +0 -106
- data/doc/js/jquery.js +0 -19
- data/doc/method_list.html +0 -219
- data/doc/top-level-namespace.html +0 -87
- data/jars/MarcImporter.jar +0 -0
- data/test/batch.seq +0 -118
- data/test/bench.rb +0 -63
- data/test/one.dat +0 -1
- data/test/one.seq +0 -30
- data/test/one.xml +0 -55
- data/test/test_marc4j4r.rb +0 -76
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
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.
|
data/Rakefile
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
+
require 'ftools'
|
3
4
|
|
4
5
|
begin
|
5
6
|
require 'jeweler'
|
6
7
|
Jeweler::Tasks.new do |gem|
|
7
8
|
gem.name = "marc4j4r"
|
8
9
|
gem.summary = %Q{Use marc4j java library in JRuby in a more ruby-ish way}
|
9
|
-
gem.description = %Q{Syntactic sugar and some extra methods to deal with
|
10
|
+
gem.description = %Q{Syntactic sugar and some extra methods to deal with MARC data using the java .jar marc4j}
|
10
11
|
gem.email = "bill@dueber.com"
|
11
|
-
gem.homepage = "http://github.com/billdueber/marc4j4r"
|
12
|
+
gem.homepage = "http://github.com/billdueber/javamarc/tree/master/ruby/marc4j4r/"
|
12
13
|
gem.authors = ["BillDueber"]
|
13
|
-
gem.add_development_dependency "
|
14
|
+
gem.add_development_dependency "bacon", ">= 0"
|
14
15
|
gem.add_development_dependency "yard", ">= 0"
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
17
|
end
|
@@ -19,19 +20,31 @@ rescue LoadError
|
|
19
20
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
21
|
end
|
21
22
|
|
23
|
+
|
24
|
+
# Make sure we've got the right .jar
|
25
|
+
LOCALJAR = 'jars/marc4j.jar'
|
26
|
+
JAVAJAR = '../../marc4j.jar'
|
27
|
+
|
28
|
+
|
29
|
+
file LOCALJAR => JAVAJAR do |t|
|
30
|
+
File.copy(JAVAJAR, LOCALJAR)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
22
35
|
require 'rake/testtask'
|
23
|
-
Rake::TestTask.new(:
|
24
|
-
|
25
|
-
|
26
|
-
|
36
|
+
Rake::TestTask.new(:spec) do |spec|
|
37
|
+
spec.libs << 'lib' << 'spec'
|
38
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
39
|
+
spec.verbose = true
|
27
40
|
end
|
28
41
|
|
29
42
|
begin
|
30
43
|
require 'rcov/rcovtask'
|
31
|
-
Rcov::RcovTask.new do |
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
Rcov::RcovTask.new do |spec|
|
45
|
+
spec.libs << 'spec'
|
46
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
47
|
+
spec.verbose = true
|
35
48
|
end
|
36
49
|
rescue LoadError
|
37
50
|
task :rcov do
|
@@ -39,9 +52,9 @@ rescue LoadError
|
|
39
52
|
end
|
40
53
|
end
|
41
54
|
|
42
|
-
task :
|
55
|
+
task :spec => [:check_dependencies, LOCALJAR]
|
43
56
|
|
44
|
-
task :default => :
|
57
|
+
task :default => :spec
|
45
58
|
|
46
59
|
begin
|
47
60
|
require 'yard'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.2
|
data/jars/marc4j.jar
CHANGED
Binary file
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MARC4J4R
|
2
|
+
ControlField = Java::org.marc4j.marc.impl::ControlFieldImpl
|
3
|
+
class ControlField
|
4
|
+
def value
|
5
|
+
return self.data
|
6
|
+
end
|
7
|
+
|
8
|
+
def value= str
|
9
|
+
self.data = str
|
10
|
+
end
|
11
|
+
|
12
|
+
def controlField?
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.control_tag? tag
|
17
|
+
return Java::org.marc4j.marc.impl.Verifier.isControlField tag
|
18
|
+
end
|
19
|
+
|
20
|
+
# Pretty-print
|
21
|
+
# @param [String] joiner What string to use to join the subfields
|
22
|
+
# @param [String] The pretty string
|
23
|
+
def to_s
|
24
|
+
return self.tag + " " + self.value
|
25
|
+
end
|
26
|
+
|
27
|
+
def == other
|
28
|
+
self.tag == other.tag && self.value == other.value
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module MARC4J4R
|
2
|
+
DataField = Java::org.marc4j.marc.impl::DataFieldImpl
|
3
|
+
SubField = Java::org.marc4j.marc.impl::SubfieldImpl
|
4
|
+
|
5
|
+
class DataField
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
alias_method :<<, :addSubfield
|
9
|
+
alias_method :add, :addSubfield
|
10
|
+
|
11
|
+
# Override the initialize to allow creation with just a tag (marc4j only allows either
|
12
|
+
# no args or the tag and both indicators)
|
13
|
+
|
14
|
+
alias_method :oldinit, :initialize
|
15
|
+
def initialize(tag = nil, ind1 = ' ', ind2 = ' ')
|
16
|
+
if tag
|
17
|
+
self.oldinit(tag, ind1[0].ord, ind2[0].ord)
|
18
|
+
else
|
19
|
+
self.oldinit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def controlField?
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
def == other
|
28
|
+
|
29
|
+
basics = ((self.tag == other.tag) and (self.indicator1 == other.indicator1) and (self.indicator2 == other.indicator2))
|
30
|
+
unless basics
|
31
|
+
# puts "Failed basics"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
selfsubs = self.to_a
|
35
|
+
othersubs = other.to_a
|
36
|
+
# puts "#{self} vs #{other}"
|
37
|
+
while (selfsubs.length > 0)
|
38
|
+
ssf = selfsubs.shift
|
39
|
+
osf = othersubs.shift
|
40
|
+
unless ssf == osf
|
41
|
+
# puts "#{ssf} <> #{osf}"
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if ((selfsubs.size > 0) or (othersubs.size > 0))
|
47
|
+
# puts "sizes unequal"
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Pretty-print
|
54
|
+
# @param [String] joiner What string to use to join the subfields
|
55
|
+
# @param [String] The pretty string
|
56
|
+
def to_s (joiner = ' ')
|
57
|
+
arr = [self.tag + ' ' + self.indicator1 + self.indicator2]
|
58
|
+
self.each do |s|
|
59
|
+
arr.push s.to_s
|
60
|
+
end
|
61
|
+
return arr.join(joiner)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Get the value of the first subfield of this field with the given code
|
66
|
+
# @param [String] code 1-character string of the subfield code
|
67
|
+
# @return [String] The value of the first matched subfield
|
68
|
+
def [] code
|
69
|
+
raise ArgumentError, "Code must be a one-character string, not #{code}" unless code.is_a? String and code.size == 1
|
70
|
+
# need to send a char value that the underlying java can deal with
|
71
|
+
sub = self.getSubfield(code[0].ord)
|
72
|
+
if (sub)
|
73
|
+
return sub.getData
|
74
|
+
else
|
75
|
+
return nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Also call it "sub" for symmatry wtih "sub_values" and "subs"
|
80
|
+
# and "first" because it makes sense
|
81
|
+
alias_method :sub, :[]
|
82
|
+
alias_method :first, :[]
|
83
|
+
|
84
|
+
# Get all subfields, optionally restricting to those with a given code
|
85
|
+
# @param [String, Array<String>] code A (array of?) 1-character strings; the code(s) to collect. Default is all
|
86
|
+
# @return [Array<MARC4J4R::SubField] The matching subfields, or an empty array
|
87
|
+
|
88
|
+
def subs code = false
|
89
|
+
unless code
|
90
|
+
return self.to_a
|
91
|
+
end
|
92
|
+
|
93
|
+
# Is it a singleton?
|
94
|
+
if not [Set, Array].include? code.class
|
95
|
+
code = [code]
|
96
|
+
end
|
97
|
+
|
98
|
+
return self.grep {|s| code.include? s.code}
|
99
|
+
end
|
100
|
+
|
101
|
+
# Get all values from the subfields for the given code or array of codes
|
102
|
+
# @param [String, Array<String>] code (Array of?) 1-character string(s) of the subfield code
|
103
|
+
# @return [Array<String>] A possibly-empty array of Strings made up of the values in the subfields whose
|
104
|
+
# code is included in the given codes (or all subfields is code is empty)
|
105
|
+
#
|
106
|
+
#
|
107
|
+
# @example Quick examples:
|
108
|
+
# # 260 $a New York, $b Van Nostrand Reinhold Co. $c 1969
|
109
|
+
# rec['260'].sub_values('a') #=> ["New York,"]
|
110
|
+
# rec['260'].sub_values(['a', 'c']) #=> ["New York,", "1969"]
|
111
|
+
# rec['260'].sub_values(['c', 'a']) #=> ["New York,", "1969"]
|
112
|
+
|
113
|
+
def sub_values(code)
|
114
|
+
return self.subs(code).collect {|s| s.value}
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# Get first indicator as a one-character string
|
119
|
+
def indicator1
|
120
|
+
return self.getIndicator1.chr
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get second indicator as a one-character string
|
124
|
+
def indicator2
|
125
|
+
return self.getIndicator2.chr
|
126
|
+
end
|
127
|
+
|
128
|
+
def indicator1= char
|
129
|
+
self.setIndicator1 char[0].ord
|
130
|
+
end
|
131
|
+
|
132
|
+
def indicator2= char
|
133
|
+
self.setIndicator2 char[0].ord
|
134
|
+
end
|
135
|
+
|
136
|
+
alias_method :ind1, :indicator1
|
137
|
+
alias_method :"ind1=", :"indicator1="
|
138
|
+
alias_method :ind2, :indicator2
|
139
|
+
alias_method :"ind2=", :"indicator2="
|
140
|
+
|
141
|
+
# Iterate over the subfields
|
142
|
+
def each
|
143
|
+
self.getSubfields.each do |s|
|
144
|
+
yield s
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Get the concatentated values of the subfields in order the appear in the field
|
149
|
+
# @param [String] joiner The string used to join the subfield values
|
150
|
+
def value joiner=' '
|
151
|
+
data = self.getSubfields.map {|s| s.data}
|
152
|
+
return data.join(joiner)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class SubField
|
157
|
+
|
158
|
+
alias_method :oldinit, :initialize
|
159
|
+
def initialize code=nil, data=nil
|
160
|
+
if code
|
161
|
+
code = code[0].ord
|
162
|
+
if data
|
163
|
+
self.oldinit(code, data)
|
164
|
+
else
|
165
|
+
self.oldinit(code)
|
166
|
+
end
|
167
|
+
else
|
168
|
+
self.oldinit
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def == other
|
173
|
+
return ((self.code == other.code) and (self.data == other.data))
|
174
|
+
end
|
175
|
+
|
176
|
+
def value
|
177
|
+
return self.data
|
178
|
+
end
|
179
|
+
|
180
|
+
def value= str
|
181
|
+
self.data = str
|
182
|
+
end
|
183
|
+
|
184
|
+
def code
|
185
|
+
return self.getCode.chr
|
186
|
+
end
|
187
|
+
|
188
|
+
def code= str
|
189
|
+
self.setCode str[0].ord
|
190
|
+
end
|
191
|
+
|
192
|
+
def to_s
|
193
|
+
return '$' + self.code + " " + self.data
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Java::OrgMarc4j::MarcReader
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
# Return the next record, after calling #hashify on it
|
5
|
+
def each(hashify=true)
|
6
|
+
while self.hasNext
|
7
|
+
r = self.next
|
8
|
+
r.hashify if hashify
|
9
|
+
yield r
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
module MARC4J4R
|
16
|
+
# Add some sugar to the MarcReader interface
|
17
|
+
#
|
18
|
+
# Adjust the interface so that a #new call to any implementations that
|
19
|
+
# implement it can take a java.io.InputStream, ruby IO obejct, or String
|
20
|
+
# (that will be interpreted as a filename) without complaining.
|
21
|
+
#
|
22
|
+
# The mechanism -- running module_eval on a string-representation of the
|
23
|
+
# new method in each of the hard-coded implementations of MarcReader
|
24
|
+
# (MarcStreamReader,MarcPermissiveStreamReader,MarcXmlReader) -- is ugly
|
25
|
+
# and deeply unsettling.
|
26
|
+
#
|
27
|
+
# @author Bill Dueber
|
28
|
+
|
29
|
+
# First, add Enumerable to the interface
|
30
|
+
Java::org.marc4j.MarcReader.module_eval("include Enumerable")
|
31
|
+
|
32
|
+
|
33
|
+
class Reader
|
34
|
+
|
35
|
+
# Get a marc reader of the appropriate type
|
36
|
+
# @param [String, IO, java.io.InputStream] input The IO stream (or filename) from which you want to read
|
37
|
+
# @param [:strictmarc, :permissivemarc, :marcxml] The type of MARC reader you want.
|
38
|
+
# @return [MarcReader] A MarcReader object with the syntactic sugar added in this file (e.g, each)
|
39
|
+
#
|
40
|
+
# @example Get a strict binary MARC reader for the file 'test.mrc'
|
41
|
+
# reader = MARC4J4R::Reader.new('test.mrc')
|
42
|
+
#
|
43
|
+
# @example Get a permissive binary MARC reader
|
44
|
+
# reader = MARC4J4R::Reader.new('test.mrc', :permissivemarc)
|
45
|
+
#
|
46
|
+
# @example Get a reader for an xml file
|
47
|
+
# reader = MARC4J4R::Reader.new('test.xml', :marcxml)
|
48
|
+
#
|
49
|
+
# @example Get a reader based on an existing IO object
|
50
|
+
# require 'open-uri'
|
51
|
+
# infile = open('http://my.machine.com/test.mrc')
|
52
|
+
# reader = MARC4J4R::Reader.new(infile)
|
53
|
+
|
54
|
+
attr_reader :handle
|
55
|
+
def self.new(input, type = :strictmarc)
|
56
|
+
@handle = IOConvert.byteinstream(input)
|
57
|
+
case type
|
58
|
+
when :strictmarc then
|
59
|
+
return Java::org.marc4j.MarcStreamReader.new(@handle)
|
60
|
+
when :permissivemarc then
|
61
|
+
return Java::org.marc4j.MarcPermissiveStreamReader.new(@handle, true, true)
|
62
|
+
when :marcxml then
|
63
|
+
return Java::org.marc4j.MarcXmlReader.new(@handle)
|
64
|
+
when :alephsequential then
|
65
|
+
return MARC4J4R::AlephSequentialReader.new(@handle)
|
66
|
+
else
|
67
|
+
raise ArgumentError, "Reader type #{type} illegal: must be :strictmarc, :permissivemarc, :marcxml, or :alephsequential"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module MARC4J4R
|
2
|
+
Record = Java::org.marc4j.marc.impl::RecordImpl
|
3
|
+
|
4
|
+
class Record
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
alias_method :<<, :addVariableField
|
8
|
+
alias_method :append, :addVariableField
|
9
|
+
alias_method :fields, :getVariableFields
|
10
|
+
|
11
|
+
# Export as a MARC-Hash, as described at
|
12
|
+
# http://robotlibrarian.billdueber.com/marc-hash-the-saga-continues-now-with-even-less-structure/
|
13
|
+
# @return A marc-hash representation of the record, suitable for calling .to_json on or whatever
|
14
|
+
|
15
|
+
# Show equality
|
16
|
+
|
17
|
+
def == other
|
18
|
+
return false unless (self.leader == other.leader)
|
19
|
+
self.zip(other) do |so|
|
20
|
+
return false unless so[0] == so[1]
|
21
|
+
end
|
22
|
+
other.zip(self) do |so|
|
23
|
+
return false unless so[0] == so[1]
|
24
|
+
end
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Create a local hash by tag number; makes some stuff faster
|
30
|
+
# Called automatically if you use reader.each
|
31
|
+
|
32
|
+
def hashify
|
33
|
+
return if @hashedtags # don't do it more than once
|
34
|
+
@hashedtags = {}
|
35
|
+
self.getVariableFields.each do |f|
|
36
|
+
@hashedtags[f.tag] ||= []
|
37
|
+
@hashedtags[f.tag].push f
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a nice string of the record
|
42
|
+
def to_s
|
43
|
+
arr = ['LEADER ' + self.leader]
|
44
|
+
self.each do |f|
|
45
|
+
arr.push f.to_s
|
46
|
+
end
|
47
|
+
return arr.join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get the leader as a string (marc4j would otherwise return Leader object)
|
51
|
+
def leader
|
52
|
+
self.get_leader.toString
|
53
|
+
end
|
54
|
+
|
55
|
+
# Set the leader
|
56
|
+
def leader= str
|
57
|
+
begin
|
58
|
+
self.set_leader Java::org.marc4j.marc.impl.LeaderImpl.new(str)
|
59
|
+
rescue java.lang.StringIndexOutOfBoundsException => e
|
60
|
+
throw RuntimeError.new("'#{str}' not a legal leader: #{e.message}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Cycle through the fields in the order the appear in the record
|
65
|
+
def each
|
66
|
+
self.getVariableFields.each do |f|
|
67
|
+
yield f
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get the first field associated with a tag
|
72
|
+
# @param [String] tag The tag
|
73
|
+
# @return [Field] The first matching field, or nil if none. Note that
|
74
|
+
# to mirror ruby-marc, this returns a single field
|
75
|
+
|
76
|
+
def [] tag
|
77
|
+
if defined? @hashedtags
|
78
|
+
if @hashedtags[tag]
|
79
|
+
return @hashedtags[tag][0]
|
80
|
+
else
|
81
|
+
return nil
|
82
|
+
end
|
83
|
+
else
|
84
|
+
return self.getVariableField(tag)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Get a (possibly empty) list of fields with the given tag(s)
|
90
|
+
#
|
91
|
+
# @param [String, Array<String>] tags A string (or Array of strings) with the tags you're interested in
|
92
|
+
# @param [Boolean] originalorder Whether or not results should be presented in the original order within the
|
93
|
+
# record or with a two-column sort of (a) Order of the tag in the list of tags sent, (b) order within that tag
|
94
|
+
# in the record
|
95
|
+
# @return [Array<Field>] Either an empty list or a list of one or more matched fields will be returned.
|
96
|
+
#
|
97
|
+
# originalorder == false will use an internal hash and be faster in many cases (see #hashify)
|
98
|
+
#
|
99
|
+
# @example originalorder == false
|
100
|
+
# # Given a record that looks like
|
101
|
+
# # 010 $a 68027371
|
102
|
+
# # 035 $a (RLIN)MIUG0001728-B
|
103
|
+
# # 035 $a (CaOTULAS)159818044
|
104
|
+
# # 035 $a (OCoLC)ocm00001728
|
105
|
+
#
|
106
|
+
# r.find_by_tag(['035', '010']).each {|f| puts f.to_s}
|
107
|
+
# # 035 $a (RLIN)MIUG0001728-B
|
108
|
+
# # 035 $a (CaOTULAS)159818044
|
109
|
+
# # 035 $a (OCoLC)ocm00001728
|
110
|
+
# # 010 $a 68027371
|
111
|
+
#
|
112
|
+
# # The results are ordered first by tag as passed in, then by original order within the tag
|
113
|
+
#
|
114
|
+
# @example Just get all fields for a single tag
|
115
|
+
# ohThirtyFives = r.find_by_tag('035')
|
116
|
+
#
|
117
|
+
# @example Get a bunch of standard identifiers
|
118
|
+
# standardIDs = r.find_by_tag(['022', '020', '010'])
|
119
|
+
#
|
120
|
+
# @example originalorder == true
|
121
|
+
# r.find_by_tag(['035', '010'], true).each {|f| puts f.to_s}
|
122
|
+
# # 010 $a 68027371
|
123
|
+
# # 035 $a (RLIN)MIUG0001728-B
|
124
|
+
# # 035 $a (CaOTULAS)159818044
|
125
|
+
# # 035 $a (OCoLC)ocm00001728
|
126
|
+
|
127
|
+
def find_by_tag(tags, originalorder = false)
|
128
|
+
self.hashify unless @hashedtags and !originalorder
|
129
|
+
if !tags.is_a? Array
|
130
|
+
return @hashedtags[tags] || []
|
131
|
+
end
|
132
|
+
if originalorder
|
133
|
+
return self.find_all {|f| tags.include? f.tag}
|
134
|
+
else
|
135
|
+
# puts "Tags is #{tags}: got #{@hashedtags.values_at(*tags)}"
|
136
|
+
return @hashedtags.values_at(*tags).flatten.compact
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
# Return the record as valid MARC-XML
|
143
|
+
# @return String A MARC-XML representation of the record, including the XML header
|
144
|
+
def to_xml
|
145
|
+
begin
|
146
|
+
xml = java.io.StringWriter.new
|
147
|
+
res = javax.xml.transform.stream.StreamResult.new(xml)
|
148
|
+
writer = org.marc4j.MarcXmlWriter.new(res)
|
149
|
+
writer.write(self)
|
150
|
+
writer.writeEndDocument
|
151
|
+
return xml.toString
|
152
|
+
rescue
|
153
|
+
"Woops! to_xml failed for record #{self['001'].data}: #{$!}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_marc
|
158
|
+
begin
|
159
|
+
s = Java::java.io.ByteArrayOutputStream.new
|
160
|
+
writer = org.marc4j.MarcStreamWriter.new(s)
|
161
|
+
writer.write(self)
|
162
|
+
@marcbinary = s.to_string
|
163
|
+
return @marcbinary
|
164
|
+
rescue
|
165
|
+
# "Woops! to_marc failed for record #{self['001'].data}: #{$!}"
|
166
|
+
"Whoops! Failed: #{$!}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def to_marchash
|
173
|
+
h = {}
|
174
|
+
h['type'] = 'marc-hash'
|
175
|
+
h['version'] = [1,0]
|
176
|
+
h['leader'] = self.leader
|
177
|
+
|
178
|
+
fields = []
|
179
|
+
|
180
|
+
self.getVariableFields.each do |f|
|
181
|
+
if f.controlField?
|
182
|
+
fields << [f.tag, f.value]
|
183
|
+
else
|
184
|
+
farray = [f.tag, f.indicator1 || ' ', f.indicator2 || ' ']
|
185
|
+
subs = []
|
186
|
+
f.each do |subfield|
|
187
|
+
subs << [subfield.code, subfield.value]
|
188
|
+
end
|
189
|
+
farray.push subs
|
190
|
+
fields << farray
|
191
|
+
end
|
192
|
+
end
|
193
|
+
h['fields'] = fields
|
194
|
+
return h
|
195
|
+
end
|
196
|
+
|
197
|
+
# Give a marc record in a string, turn it into an object
|
198
|
+
# @param String str The record as a MARC binary string
|
199
|
+
# @return MARC4J4R::Record The first record encoded in the string
|
200
|
+
def self.from_string str
|
201
|
+
return MARC4J4R::Reader.new(StringIO.new(str)).first
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
# Give a marc-xml record in a string, turn it into an object
|
206
|
+
# @param String str The record as a MARC-XML string
|
207
|
+
# @return MARC4J4R::Record The first record encoded in the string
|
208
|
+
def self.from_xml_string str
|
209
|
+
return MARC4J4R::Reader.new(StringIO.new(str), :marcxml).first
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
end
|
214
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MARC4J4R
|
2
|
+
# Add some sugar to the MarcWriter interface
|
3
|
+
#
|
4
|
+
# Adjust the interface so that a #new call to any implementations that
|
5
|
+
# implement it can take a java.io.InputStream, ruby IO object, or String
|
6
|
+
# (that will be interpreted as a filename) without complaining.
|
7
|
+
#
|
8
|
+
# The mechanism -- running module_eval on a string-representation of the
|
9
|
+
# new method in each of the hard-coded implementations -- is ugly
|
10
|
+
# and deeply unsettling.
|
11
|
+
#
|
12
|
+
# @author Bill Dueber
|
13
|
+
#
|
14
|
+
|
15
|
+
class Writer
|
16
|
+
|
17
|
+
# A simple factory to return the correct type of writer
|
18
|
+
def self.new output, type = :strictmarc
|
19
|
+
@handle = IOConvert.byteoutstream(output)
|
20
|
+
if type == :strictmarc
|
21
|
+
return Java::org.marc4j.MarcStreamWriter.new(@handle)
|
22
|
+
elsif type == :marcxml
|
23
|
+
return Java::org.marc4j.MarcStreamWriter.new(@handle)
|
24
|
+
else
|
25
|
+
raise ArgumentError.new("#{type} must be :strictmarc or :marcxml")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|