rsinger-enhanced_marc 0.1 → 0.1.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 +2 -2
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/enhanced_marc-0.1.gem +0 -0
- data/lib/enhanced_marc/book_record.rb +37 -0
- data/lib/enhanced_marc/book_type.rb +86 -0
- data/lib/enhanced_marc/computer_record.rb +37 -0
- data/lib/enhanced_marc/computer_type.rb +14 -0
- data/lib/enhanced_marc/leader.rb +132 -0
- data/lib/enhanced_marc/leftovers.rb +122 -0
- data/lib/enhanced_marc/map_record.rb +38 -0
- data/lib/enhanced_marc/map_type.rb +99 -0
- data/lib/enhanced_marc/mixed_record.rb +37 -0
- data/lib/enhanced_marc/mixed_type.rb +4 -0
- data/lib/enhanced_marc/reader.rb +101 -0
- data/lib/enhanced_marc/record.rb +81 -0
- data/lib/enhanced_marc/record_type.rb +309 -0
- data/lib/enhanced_marc/score_record.rb +38 -0
- data/lib/enhanced_marc/score_type.rb +4 -0
- data/lib/enhanced_marc/serial_record.rb +37 -0
- data/lib/enhanced_marc/serial_type.rb +87 -0
- data/lib/enhanced_marc/sound_record.rb +37 -0
- data/lib/enhanced_marc/sound_type.rb +4 -0
- data/lib/enhanced_marc/visual_record.rb +37 -0
- data/lib/enhanced_marc/visual_type.rb +38 -0
- data/lib/enhanced_marc/xmlreader.rb +58 -0
- data/lib/enhanced_marc.rb +22 -0
- data/pkg/enhanced_marc-0.1/Changes +1 -0
- data/pkg/enhanced_marc-0.1/LICENSE +21 -0
- data/pkg/enhanced_marc-0.1/README +51 -0
- data/pkg/enhanced_marc-0.1/Rakefile +23 -0
- data/pkg/enhanced_marc-0.1/test/ts_enhanced_marc.rb +5 -0
- data/pkg/enhanced_marc-0.1.gem +0 -0
- data/pkg/enhanced_marc-0.1.tgz +0 -0
- data/pkg/enhanced_marc-0.1.zip +0 -0
- metadata +47 -12
@@ -0,0 +1,38 @@
|
|
1
|
+
module MARC
|
2
|
+
|
3
|
+
# A class that represents an individual MARC record. Every record
|
4
|
+
# is made up of a collection of MARC::Field objects.
|
5
|
+
|
6
|
+
class MapRecord < Record
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
@leader[6] = 'e' if @leader[6,1] == ' '
|
11
|
+
@leader[7] = 'm' if @leader[7,1] == ' '
|
12
|
+
@record_type = 'MAP'
|
13
|
+
@bibliographic_level = @leader.get_blvl
|
14
|
+
self.extend MapType
|
15
|
+
self.inspect_fixed_fields
|
16
|
+
end
|
17
|
+
|
18
|
+
def is_valid_type?
|
19
|
+
return false unless @leader[6,1].match(/[ef]{1}/)
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
def is_valid_blvl?
|
23
|
+
return true if @leader[7,1].match(/[acdim]{1}/) and @leader[6,1].match('f')
|
24
|
+
return true if @leader[7,1].match(/[abcdims]{1}/) and @leader[6,1].match('e')
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
def self.new_from_record(record)
|
28
|
+
rec = MapRecord.new
|
29
|
+
record.instance_variables.each { | var |
|
30
|
+
rec.instance_variable_set(var, record.instance_variable_get(var))
|
31
|
+
}
|
32
|
+
return Exception.new("Incorrect type declaration in leader") unless rec.is_valid_type?
|
33
|
+
return Exception.new("Incorrect bibliographic declaration in leader") unless rec.is_valid_blvl?
|
34
|
+
return rec
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module MapType
|
2
|
+
include RecordType
|
3
|
+
public :is_govdoc?, :form, :has_index?
|
4
|
+
def cartographic_type(human_readable=false)
|
5
|
+
crtp_map = {'a'=>'Map', 'b'=>'Map series', 'c'=>'Map serial', 'd'=>'Globe', 'e'=>'Atlas',
|
6
|
+
'f'=>'Supplement', 'g'=>'Bound as part of another work', 'u'=>'Unknown', 'z'=>'Other'}
|
7
|
+
human_readable = crtp_map if human_readable
|
8
|
+
return self.field_parser({:match=>'MAP', :start=>25,:end=>1}, {:match=>/[ef]{1}/, :start=>8,:end=>1}, human_readable)
|
9
|
+
end
|
10
|
+
|
11
|
+
def relief(human_readable=false)
|
12
|
+
relief_map = {'a'=>'Contours', 'b'=>'Shading', 'c'=>'Grading and bathymetric tints',
|
13
|
+
'd'=>'Hachures', 'e'=>'Bathymetry, soundings', 'f'=>'Form lines', 'g'=>'Spot heights',
|
14
|
+
'h'=>'Color', 'i'=>'Pictorially', 'j'=>'Land forms', 'k'=>'Bathymetry, isolines',
|
15
|
+
'm'=>'Rock drawings', 'z'=>'Other'
|
16
|
+
}
|
17
|
+
contents = []
|
18
|
+
if self.record_type == 'MAP'
|
19
|
+
self['008'].value[18,4].split(//).each { | char |
|
20
|
+
next if char == " "
|
21
|
+
if human_readable
|
22
|
+
contents << relief_map[char]
|
23
|
+
else
|
24
|
+
contents << char
|
25
|
+
end
|
26
|
+
}
|
27
|
+
end
|
28
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
29
|
+
next unless fxd_fld.value[0,1].match(/[ef]{1}/)
|
30
|
+
fxd_fld.value[1,4].split(//).each { | char |
|
31
|
+
next if char == " "
|
32
|
+
if human_readable
|
33
|
+
contents << relief_map[char]
|
34
|
+
else
|
35
|
+
contents << char
|
36
|
+
end
|
37
|
+
}
|
38
|
+
}
|
39
|
+
return false if contents.empty?
|
40
|
+
return contents
|
41
|
+
end
|
42
|
+
|
43
|
+
def projection(human_readable=false)
|
44
|
+
proj_map = {'Azimuthal'=>{'aa'=>'Aitoff','ab'=>'Gnomic','ac'=>"Lambert's equal area",
|
45
|
+
'ad'=>'Orthographic','ae'=>'Azithumal equidistant', 'af'=>'Stereographic',
|
46
|
+
'ag'=>'General vertical near-sided','am'=>'Modified stereographic for Alaska',
|
47
|
+
'an'=>'Chamberlin trimetric','ap'=>'Polar stereographic','au'=>'Unknown','az'=>'Other'},
|
48
|
+
'Cylindrical'=>{'ba'=>'Gall','bb'=>"Goode's homolographic",'bc'=>"Lambert's equal area",
|
49
|
+
'bd'=>'Mercator','be'=>'Miller','bf'=>'Mollweide','bg'=>'Sinusoidal',
|
50
|
+
'bh'=>'Transverse Mercator','bi'=>'Gauss-Kruger','bj'=>'Equirectangular',
|
51
|
+
'bo'=>'Oblique Mercator','br'=>'Robinson','bs'=>'Space oblique Mercator',
|
52
|
+
'bu'=>'Unknown','bz'=>'Other'
|
53
|
+
},
|
54
|
+
'Conic'=>{'ca'=>"Alber's equal area",'cb'=>'Bonne','cc'=>"Lambert's",'ce'=>'Equidistant conic',
|
55
|
+
'cp'=>'Polyconic','cu'=>'Unknown','cz'=>'Other'
|
56
|
+
},
|
57
|
+
'Other'=>{'da'=>'Armadillo','db'=>'Butterfly','dc'=>'Eckert','dd'=>"Goode's homolosine",
|
58
|
+
'de'=>"Miller's bipolar oblique conformal conic",'df'=>'Van Der Grinten',
|
59
|
+
'dg'=>'Dymaxion','dh'=>'Cordiform','dl'=>'Lambert conformal','zz'=>'Other'
|
60
|
+
}
|
61
|
+
}
|
62
|
+
if @record_type == "MAP"
|
63
|
+
unless self['008'].value[22,2] == ' '
|
64
|
+
if human_readable
|
65
|
+
proj_map.each_key { | general |
|
66
|
+
next unless proj_map[general].keys.index(self['008'].value[22,2])
|
67
|
+
return [general,proj_map[general][self['008'].value[22,2]]]
|
68
|
+
}
|
69
|
+
else
|
70
|
+
return self['008'].value[22,2]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
75
|
+
next unless fxd_fld.value[0,1].match(/[ef]{1}/)
|
76
|
+
unless fxd_fld.value[5,2] == ' '
|
77
|
+
if human_readable
|
78
|
+
proj_map.each_key { | general |
|
79
|
+
next unless proj_map[general].keys.index(fxd_fld.value[5,2])
|
80
|
+
return [general,proj_map[general][fxd_fld.value[5,2]]]
|
81
|
+
}
|
82
|
+
else
|
83
|
+
return fxd_fld.value[5,2]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
}
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
|
90
|
+
def special_format(human_readable=false)
|
91
|
+
spfm_map = {'a'=>'Blueprint photocopy','b'=>'Other photocopy','c'=>'Negative photocopy',
|
92
|
+
'd'=>'Film negative','f'=>'Facsimile','g'=>'Relief model','h'=>'Rare (pre-1800)',
|
93
|
+
'e'=>'Manuscript','j'=>'Picture/post card','k'=>'Calendar','l'=>'Puzzle',
|
94
|
+
'm'=>'Braille, tactile','n'=>'Game','o'=>'Wall map','p'=>'Playing cards',
|
95
|
+
'q'=>'Loose-leaf','z'=>'Other'}
|
96
|
+
human_readable = spfm_map if human_readable
|
97
|
+
return self.field_parser({:match=>'MAP', :start=>33,:end=>2}, {:match=>/[ef]{1}/, :start=>16,:end=>2}, human_readable)
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module MARC
|
2
|
+
|
3
|
+
# A class that represents an individual MARC record. Every record
|
4
|
+
# is made up of a collection of MARC::Field objects.
|
5
|
+
|
6
|
+
class MixedRecord < Record
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
@leader[6] = 'p' if @leader[6,1] == ' '
|
11
|
+
@leader[7] = 'c' if @leader[7,1] == ' '
|
12
|
+
@record_type = 'MIX'
|
13
|
+
@bibliographic_level = @leader.get_blvl
|
14
|
+
self.extend MixedType
|
15
|
+
self.inspect_fixed_fields
|
16
|
+
end
|
17
|
+
|
18
|
+
def is_valid_type?
|
19
|
+
return false unless @leader[6,1].match('p')
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
def is_valid_blvl?
|
23
|
+
return false unless @leader[7,1].match(/[cdi]{1}/)
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
def self.new_from_record(record)
|
27
|
+
rec = MixedRecord.new
|
28
|
+
record.instance_variables.each { | var |
|
29
|
+
rec.instance_variable_set(var, record.instance_variable_get(var))
|
30
|
+
}
|
31
|
+
return Exception.new("Incorrect type declaration in leader") unless rec.is_valid_type?
|
32
|
+
return Exception.new("Incorrect bibliographic declaration in leader") unless rec.is_valid_blvl?
|
33
|
+
return rec
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module MARC
|
2
|
+
class Reader
|
3
|
+
# A static method for turning raw MARC data in transission
|
4
|
+
# format into a MARC::Record object.
|
5
|
+
def self.decode(marc, params={})
|
6
|
+
leader = Leader.new(marc[0..LEADER_LENGTH-1])
|
7
|
+
record = case leader.get_type
|
8
|
+
when 'BKS' then MARC::BookRecord.new
|
9
|
+
when 'SER' then MARC::SerialRecord.new
|
10
|
+
when 'VIS' then MARC::VisualRecord.new
|
11
|
+
when 'MIX' then MARC::MixedRecord.new
|
12
|
+
when 'MAP' then MARC::MapRecord.new
|
13
|
+
when 'SCO' then MARC::ScoreRecord.new
|
14
|
+
when 'REC' then MARC::SoundRecord.new
|
15
|
+
when 'COM' then MARC::ComputerRecord.new
|
16
|
+
else MARC::Record.new
|
17
|
+
end
|
18
|
+
record.leader = leader
|
19
|
+
|
20
|
+
# where the field data starts
|
21
|
+
base_address = record.leader[12..16].to_i
|
22
|
+
|
23
|
+
# get the byte offsets from the record directory
|
24
|
+
directory = marc[LEADER_LENGTH..base_address-1]
|
25
|
+
|
26
|
+
throw "invalid directory in record" if directory == nil
|
27
|
+
|
28
|
+
# the number of fields in the record corresponds to
|
29
|
+
# how many directory entries there are
|
30
|
+
num_fields = directory.length / DIRECTORY_ENTRY_LENGTH
|
31
|
+
|
32
|
+
# when operating in forgiving mode we just split on end of
|
33
|
+
# field instead of using calculated byte offsets from the
|
34
|
+
# directory
|
35
|
+
all_fields = marc[base_address..-1].split(END_OF_FIELD)
|
36
|
+
|
37
|
+
0.upto(num_fields-1) do |field_num|
|
38
|
+
|
39
|
+
# pull the directory entry for a field out
|
40
|
+
entry_start = field_num * DIRECTORY_ENTRY_LENGTH
|
41
|
+
entry_end = entry_start + DIRECTORY_ENTRY_LENGTH
|
42
|
+
entry = directory[entry_start..entry_end]
|
43
|
+
|
44
|
+
# extract the tag
|
45
|
+
tag = entry[0..2]
|
46
|
+
|
47
|
+
# get the actual field data
|
48
|
+
# if we were told to be forgiving we just use the
|
49
|
+
# next available chuck of field data that we
|
50
|
+
# split apart based on the END_OF_FIELD
|
51
|
+
field_data = ''
|
52
|
+
if params[:forgiving]
|
53
|
+
field_data = all_fields.shift()
|
54
|
+
|
55
|
+
# otherwise we actually use the byte offsets in
|
56
|
+
# directory to figure out what field data to extract
|
57
|
+
else
|
58
|
+
length = entry[3..6].to_i
|
59
|
+
offset = entry[7..11].to_i
|
60
|
+
field_start = base_address + offset
|
61
|
+
field_end = field_start + length - 1
|
62
|
+
field_data = marc[field_start..field_end]
|
63
|
+
end
|
64
|
+
|
65
|
+
# remove end of field
|
66
|
+
field_data.delete!(END_OF_FIELD)
|
67
|
+
|
68
|
+
# add a control field or data field
|
69
|
+
if tag < '010'
|
70
|
+
record.append(MARC::ControlField.new(tag,field_data))
|
71
|
+
else
|
72
|
+
field = MARC::DataField.new(tag)
|
73
|
+
|
74
|
+
# get all subfields
|
75
|
+
subfields = field_data.split(SUBFIELD_INDICATOR)
|
76
|
+
|
77
|
+
# must have at least 2 elements (indicators, and 1 subfield)
|
78
|
+
# TODO some sort of logging?
|
79
|
+
next if subfields.length() < 2
|
80
|
+
|
81
|
+
# get indicators
|
82
|
+
indicators = subfields.shift()
|
83
|
+
field.indicator1 = indicators[0,1]
|
84
|
+
field.indicator2 = indicators[1,1]
|
85
|
+
|
86
|
+
# add each subfield to the field
|
87
|
+
subfields.each() do |data|
|
88
|
+
subfield = MARC::Subfield.new(data[0,1],data[1..-1])
|
89
|
+
field.append(subfield)
|
90
|
+
end
|
91
|
+
|
92
|
+
# add the field to the record
|
93
|
+
record.append(field)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
return record
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module MARC
|
2
|
+
class Record
|
3
|
+
|
4
|
+
attr_reader :record_type, :bibliographic_level
|
5
|
+
|
6
|
+
# Creates a new MARC::Record using MARC::Leader
|
7
|
+
# to work with the leader, rather than a string
|
8
|
+
def initialize
|
9
|
+
@fields = []
|
10
|
+
@leader = Leader.new(' ' * 24)
|
11
|
+
end
|
12
|
+
|
13
|
+
def contains_type?(record_type)
|
14
|
+
type_map = {"BKS"=>/[at]{1}/, "COM"=>"m", "MAP"=>/[ef]{1}/,"MIX"=>"p", "SCO"=>/[cd]{1}/, "REC"=>/[ij]{1}/, "SER"=>"s", "VIS"=>/[gkor]{1}/}
|
15
|
+
matching_fields = []
|
16
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
17
|
+
matching_fields << fxd_fld if fxd_fld.value[0,1].match(type_map[record_type])
|
18
|
+
|
19
|
+
}
|
20
|
+
return nil if matching_fields.empty?
|
21
|
+
return matching_fields
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.new_from_record(record)
|
25
|
+
leader = Leader.new(record.leader)
|
26
|
+
case leader.get_type
|
27
|
+
when 'BKS' then return MARC::BookRecord.new_from_record(record)
|
28
|
+
when 'SER' then return MARC::SerialRecord.new_from_record(record)
|
29
|
+
when 'VIS' then return MARC::VisualRecord.new_from_record(record)
|
30
|
+
when 'MIX' then return MARC::MixedRecord.new_from_record(record)
|
31
|
+
when 'MAP' then return MARC::MapRecord.new_from_record(record)
|
32
|
+
when 'SCO' then return MARC::ScoreRecord.new_from_record(record)
|
33
|
+
when 'REC' then return MARC::SoundRecord.new_from_record(record)
|
34
|
+
when 'COM' then return MARC::ComputerRecord.new_from_record(record)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_typed_record
|
39
|
+
return self.new_from_record(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_archival?
|
43
|
+
return @leader.is_archival?
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def composition_form(human_readable=false)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def publication_country
|
52
|
+
return self['008'].value[15,2] unless self['008'].value[15,2] == ' '
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_dates
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def created_on
|
61
|
+
unless self['008'].value[0,6] == (' '*6)
|
62
|
+
return Date.parse(self['008'].value[0,2]+'-'+self['008'].value[2,2]+'-'+self['008'].value[4,2], false)
|
63
|
+
else
|
64
|
+
return Date.today
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def inspect_fixed_fields
|
69
|
+
type_map = {/[at]{1}/=>BookType,'m'=>ComputerType,/[ef]{1}/=>MapType,
|
70
|
+
'p'=>MixedType,/[cd]{1}/=>ScoreType,/[ij]{1}/=>SoundType,'s'=>SerialType,
|
71
|
+
/[gkor]{1}/=>VisualType}
|
72
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
73
|
+
type_map.each_key { | key |
|
74
|
+
if fxd_fld.value[0,1].match(key)
|
75
|
+
self.extend type_map[key]
|
76
|
+
end
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
module RecordType
|
2
|
+
|
3
|
+
private
|
4
|
+
|
5
|
+
def is_govdoc?(human_readable=false)
|
6
|
+
govdoc_map={'a'=>'Autonomous or semiautonomous components', 'c'=>'Multilocal', 'f'=>'Federal',
|
7
|
+
'i'=>'International', 'l'=>'Local', 'm'=>'Multistate', 'o'=>'Undetermined', 's'=>'State', 'u'=>'Unknown', 'z'=>'Other'}
|
8
|
+
human_readable = govdoc_map if human_readable
|
9
|
+
return self.field_parser({:match=>/^BKS$|^COM$|^MAP$|^SER$|^VIS$/, :start=>28,:end=>1}, {:match=>/[atmefsgkor]{1}/, :start=>11,:end=>1}, human_readable)
|
10
|
+
end
|
11
|
+
|
12
|
+
def nature_of_contents(human_readable=false)
|
13
|
+
cont_map = {'a'=>'Abstracts','b'=>'Bibliography','c'=>'Catalog','d'=>'Dictionary',
|
14
|
+
'e'=>'Encyclopedia', 'f'=>'Handbook', 'g'=>'Legal article', 'h'=>'Biography', 'i'=>'Index',
|
15
|
+
'j'=>'Patent document', 'k'=>'Discography', 'l'=>'Legislation', 'm'=>'Thesis', 'n'=>'Literature survey',
|
16
|
+
'o'=>'Review', 'p'=>'Programmed text', 'q'=>'Filmography', 'r'=>'Directory', 's'=>'Statistics',
|
17
|
+
't'=>'Technical report', 'u'=>'Standard/specification', 'v'=>'Legal case', 'w'=>'Law report', 'x'=>'Other report',
|
18
|
+
'z'=>'Treaty'}
|
19
|
+
contents = []
|
20
|
+
idx = nil
|
21
|
+
if self.record_type == 'BKS'
|
22
|
+
idx = 24
|
23
|
+
len = 4
|
24
|
+
elsif self.record_type == 'SER'
|
25
|
+
idx = 25
|
26
|
+
len = 3
|
27
|
+
end
|
28
|
+
if idx
|
29
|
+
self['008'].value[idx,len].split(//).each { | char |
|
30
|
+
next if char == " "
|
31
|
+
if human_readable
|
32
|
+
contents << cont_map[char]
|
33
|
+
else
|
34
|
+
contents << char
|
35
|
+
end
|
36
|
+
}
|
37
|
+
end
|
38
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
39
|
+
idx = nil
|
40
|
+
if fxd_fld.value[0,1].match(/[at]{1}/)
|
41
|
+
idx = 7
|
42
|
+
len = 4
|
43
|
+
elsif fxd_fld.value[0,1].match('s')
|
44
|
+
idx = 8
|
45
|
+
len = 3
|
46
|
+
end
|
47
|
+
if idx
|
48
|
+
fxd_fld.value[idx,len].split(//).each { | char |
|
49
|
+
next if char == " "
|
50
|
+
if human_readable
|
51
|
+
contents << cont_map[char]
|
52
|
+
else
|
53
|
+
contents << char
|
54
|
+
end
|
55
|
+
}
|
56
|
+
end
|
57
|
+
}
|
58
|
+
return false if contents.empty?
|
59
|
+
return contents
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def is_conference?
|
64
|
+
return true if self['008'].value[29,1] == '1' && @record_type.match(/^BKS$|^SER$/)
|
65
|
+
return true if self['008'].value[30,2].match(/c/) && @record_type.match(/^SCO$|^REC$/)
|
66
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
67
|
+
return true if fxd_fld.value[12,1] == '1' && fxd_fld.value[0,1].match(/[ats]{1}/)
|
68
|
+
|
69
|
+
return true if fxd_fld.value[13,2].match(/c/) && fxd_fld.value[0,1].match(/[cdij]{1}/)
|
70
|
+
}
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_conference(value=false, field=nil)
|
75
|
+
if field
|
76
|
+
return Exception.new("Field is not an 006") unless field.tag == '006'
|
77
|
+
return Exception.new("Field is not a BKS or SER") unless field.value[0,1].match(/[ats]{1}/)
|
78
|
+
if value
|
79
|
+
field.value[12] = '1'
|
80
|
+
else
|
81
|
+
field.value[12] = '0'
|
82
|
+
end
|
83
|
+
else
|
84
|
+
field = @fields['008']
|
85
|
+
field = MARC::Controlfield.new('008') unless field
|
86
|
+
if value
|
87
|
+
field[29] = '1'
|
88
|
+
else
|
89
|
+
field[29] = '0'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def accompanying_matter(human_readable=false)
|
96
|
+
accm_map = {'a'=>'Discography','b'=>'Bibliography','c'=>'Thematic index','d'=>'Libretto',
|
97
|
+
'e'=>'Composer biography', 'f'=>'Performer biography', 'g'=>'Technical/historical information on instruments',
|
98
|
+
'h'=>'Technical information on music', 'i'=>'Historical information',
|
99
|
+
'k'=>'Ethnological information', 'r'=>'Instructional materials', 's'=>'Music',
|
100
|
+
'z'=>'Other accompanying matter'}
|
101
|
+
matter = []
|
102
|
+
|
103
|
+
if ['SCO', 'REC'].index(@record_type)
|
104
|
+
self['008'].value[24,6].split(//).each { | char |
|
105
|
+
next if char == " "
|
106
|
+
if human_readable
|
107
|
+
matter << accm_map[char]
|
108
|
+
else
|
109
|
+
matter << char
|
110
|
+
end
|
111
|
+
}
|
112
|
+
end
|
113
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
114
|
+
|
115
|
+
if fxd_fld.value[0,1].match(/[cdij]{1}/)
|
116
|
+
fxd_fld.value[7,6].split(//).each { | char |
|
117
|
+
next if char == " "
|
118
|
+
if human_readable
|
119
|
+
matter << accm_map[char]
|
120
|
+
else
|
121
|
+
matter << char
|
122
|
+
end
|
123
|
+
}
|
124
|
+
end
|
125
|
+
}
|
126
|
+
return false if matter.empty?
|
127
|
+
return matter
|
128
|
+
end
|
129
|
+
|
130
|
+
def audience_level(human_readable=false)
|
131
|
+
audn_map = {'a'=>'Preschool', 'b'=>'Children age 6-8', 'c'=>'Children age 9-13',
|
132
|
+
'd'=>'Adolescent', 'e'=>'Adult', 'f'=>'Specialized', 'g'=>'General', 'j'=>'Juvenile'
|
133
|
+
}
|
134
|
+
human_readable = audn_map if human_readable
|
135
|
+
return self.field_parser({:match=>/^BKS$|^VIS$|^MIX$|^MAP$|^SCO$|^REC$|^COM$/, :start=>22,:end=>1}, {:match=>/[atmefpcdijgkor]{1}/, :start=>5,:end=>1}, human_readable)
|
136
|
+
end
|
137
|
+
|
138
|
+
def form(human_readable=false)
|
139
|
+
form_map = {'a'=>'Microfilm', 'b'=>'Microfiche', 'c'=>'Microopaque',
|
140
|
+
'd'=>'Large print', 'f'=>'Braille', 'r'=>'Reproduction', 's'=>'Electronic'
|
141
|
+
}
|
142
|
+
idx = nil
|
143
|
+
if self.record_type.match(/^MAP$|^VIS$/)
|
144
|
+
idx = 29
|
145
|
+
else
|
146
|
+
idx = 23
|
147
|
+
end
|
148
|
+
unless self['008'].value[idx,1] == ' '
|
149
|
+
if human_readable
|
150
|
+
return form_map[self['008'].value[idx,1]]
|
151
|
+
else
|
152
|
+
return self['008'].value[idx,1]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
156
|
+
idx = nil
|
157
|
+
if fxd_fld.value[0,1].match(/[efgkor]{1}/)
|
158
|
+
idx = 6
|
159
|
+
else
|
160
|
+
idx = 12
|
161
|
+
end
|
162
|
+
next if fxd_fld.value[idx,1] == ' '
|
163
|
+
if human_readable
|
164
|
+
return form_map[fxd_fld.value[idx,1]]
|
165
|
+
else
|
166
|
+
return fxd_fld.value[idx,1]
|
167
|
+
end
|
168
|
+
}
|
169
|
+
return false
|
170
|
+
end
|
171
|
+
|
172
|
+
def has_index?
|
173
|
+
return true if self['008'].value[31,1] == '1'
|
174
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
175
|
+
return true if fxd_fld.value[14,1] == '1'
|
176
|
+
}
|
177
|
+
return false
|
178
|
+
end
|
179
|
+
|
180
|
+
def composition_form(human_readable=false)
|
181
|
+
comp_map = {'an'=>'Anthem','bd'=>'Ballad','bt'=>'Ballet','bg'=>'Bluegrass music',
|
182
|
+
'bl'=>'Blues','cn'=>'Canon or round','ct'=>'Catata','cz'=>'Canzona','cr'=>'Carol',
|
183
|
+
'ca'=>'Chaconne','cs'=>'Chance composition','cp'=>'Polyphonic chanson','cc'=>'Christian chant',
|
184
|
+
'cb'=>'Chant','cl'=>'Chorale prelude','ch'=>'Chorale','cg'=>'Concerti grossi','co'=>'Concerto',
|
185
|
+
'cy'=>'Country music','df'=>'Dance form','dv'=>'Divertimento/serenade/cassation/divertissement/notturni',
|
186
|
+
'ft'=>'Fantasia','fm'=>'Folk music','fg'=>'Fugue','gm'=>'Gospel music','hy'=>"Hymn",'jz'=>'Jazz',
|
187
|
+
'md'=>'Madrigal','mr'=>'March','ms'=>'Mass','mz'=>'Mazurka','mi'=>'Minuet','mo'=>'Motet',
|
188
|
+
'mp'=>'Motion picture music','mu'=>'Multiple forms','mc'=>'Musical revue/comedy',
|
189
|
+
'nc'=>'Nocturne','nn'=>'Not a musical recording','op'=>'Opera','or'=>'Oratorio',
|
190
|
+
'ov'=>'Overture','pt'=>'Part-song','ps'=>'Passacaglia','pm'=>'Passion music',
|
191
|
+
'pv'=>'Pavanes','po'=>'Polonaises','pp'=>'Popular music','pr'=>'Prelude','pg'=>'Program music',
|
192
|
+
'rg'=>'Ragtime music','rq'=>'Requiem','rp'=>'Rhapsody','ri'=>'Ricercars','rc'=>'Rock music',
|
193
|
+
'rd'=>'Rondo','sn'=>'Sonata','sg'=>'Song','sd'=>'Square dance music','st'=>'Study/exercise',
|
194
|
+
'su'=>'Suite','sp'=>'Symphonic poem','sy'=>'Symphony','tc'=>'Toccata','ts'=>'Trio-sonata',
|
195
|
+
'uu'=>'Unknown','vr'=>'Variation','wz'=>'Waltz','zz'=>'Other'
|
196
|
+
}
|
197
|
+
if @record_type.match(/^SCO$|^REC$/)
|
198
|
+
unless self['008'].value[18,2] == ' '
|
199
|
+
if human_readable
|
200
|
+
return comp_map[self['008'].value[18,2]]
|
201
|
+
else
|
202
|
+
return self['008'].value[18,2]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
207
|
+
next unless fxd_fld.value[0,1].match(/[cdij]{1}/)
|
208
|
+
unless fxd_fld.value[1,2] == ' '
|
209
|
+
if human_readable
|
210
|
+
return comp_map[fxd_fld.value[1,2]]
|
211
|
+
else
|
212
|
+
return fxd_fld.value[1,2]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
}
|
216
|
+
return false
|
217
|
+
end
|
218
|
+
|
219
|
+
def music_format(human_readable=false)
|
220
|
+
fmus_map = {'a'=>'Full score','b'=>'Full score, miniature/study size','c'=>'Accompaniment reduced for keyboard',
|
221
|
+
'd'=>'Voice score','e'=>'Condensed score','g'=>'Close score','m'=>'Multiple formats','n'=>'N/A',
|
222
|
+
'u'=>'Unknown','z'=>'Other'}
|
223
|
+
human_readable = fmus_map if human_readable
|
224
|
+
return self.field_parser({:match=>/^SCO$|^REC$/, :start=>20,:end=>1}, {:match=>/[cdij]{1}/, :start=>3,:end=>1}, human_readable)
|
225
|
+
# if self.record_type.match(/^SCO$|^REC$/)
|
226
|
+
# unless self['008'].value[20,1] == ' '
|
227
|
+
# if human_readable
|
228
|
+
# return fmus_map[self['008'].value[20,1]]
|
229
|
+
# else
|
230
|
+
# return self['008'].value[20,1]
|
231
|
+
# end
|
232
|
+
# end
|
233
|
+
# end
|
234
|
+
## @fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
235
|
+
# next unless fxd_fld.value[0,1].match(/[cdij]{1}/)
|
236
|
+
# next if fxd_fld.value[3,1] == ' '
|
237
|
+
# if human_readable
|
238
|
+
# return fmus_map[fxd_fld.value[3,1]]
|
239
|
+
# else
|
240
|
+
# return fxd_fld.value[3,1]
|
241
|
+
# end
|
242
|
+
# }
|
243
|
+
# return false
|
244
|
+
end
|
245
|
+
|
246
|
+
def has_index?
|
247
|
+
return true if self['008'].value[31,1] == '1'
|
248
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
249
|
+
return true if fxd_fld.value[14,1] == '1'
|
250
|
+
}
|
251
|
+
return false
|
252
|
+
end
|
253
|
+
|
254
|
+
def literary_text(human_readable=true)
|
255
|
+
ltxt_map = {'a'=>'Autobiography', 'b'=>'Biography','c'=>'Conference proceeding','d'=>'Drama',
|
256
|
+
'e'=>'Essay','f'=>'Fiction','g'=>'Reporting','h'=>'History','i'=>'Instruction','j'=>'Language instruction',
|
257
|
+
'k'=>'Comedy','l'=>'Lecture/speech','m'=>'Memoir','n'=>'N/A','o'=>'Folktale','p'=>'Poetry','r'=>'Rehearsal',
|
258
|
+
's'=>'Sounds','t'=>'Interview','z'=>'Other'}
|
259
|
+
txts = []
|
260
|
+
|
261
|
+
if ['SCO', 'REC'].index(@record_type)
|
262
|
+
self['008'].value[30,2].split(//).each { | char |
|
263
|
+
next if char == " "
|
264
|
+
if human_readable
|
265
|
+
txts << ltxt_map[char]
|
266
|
+
else
|
267
|
+
txts << char
|
268
|
+
end
|
269
|
+
}
|
270
|
+
end
|
271
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
272
|
+
|
273
|
+
if fxd_fld.value[0,1].match(/[cdij]{1}/)
|
274
|
+
fxd_fld.value[13,2].split(//).each { | char |
|
275
|
+
next if char == " "
|
276
|
+
if human_readable
|
277
|
+
txts << ltxt_map[char]
|
278
|
+
else
|
279
|
+
txts << char
|
280
|
+
end
|
281
|
+
}
|
282
|
+
end
|
283
|
+
}
|
284
|
+
return false if txts.empty?
|
285
|
+
return txts
|
286
|
+
end
|
287
|
+
protected
|
288
|
+
def field_parser(eight, six, human_readable_map=nil)
|
289
|
+
if self.record_type.match(eight[:match])
|
290
|
+
unless self['008'].value[eight[:start],eight[:end]] == ' '*eight[:end]
|
291
|
+
if human_readable_map
|
292
|
+
return human_readable_map[self['008'].value[eight[:start],eight[:end]]]
|
293
|
+
else
|
294
|
+
return self['008'].value[eight[:start],eight[:end]]
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
@fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
|
299
|
+
next unless fxd_fld.value[0,1].match(six[:match])
|
300
|
+
next if fxd_fld.value[six[:start],six[:end]] == ' '*six[:end]
|
301
|
+
if human_readable_map
|
302
|
+
return human_readable_map[fxd_fld.value[six[:start],six[:end]]]
|
303
|
+
else
|
304
|
+
return fxd_fld.value[six[:start],six[:end]]
|
305
|
+
end
|
306
|
+
}
|
307
|
+
return false
|
308
|
+
end
|
309
|
+
end
|