rsinger-enhanced_marc 0.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,7 +1,7 @@
1
- Enhanced MARC is a set of classes, modules and methods that sit on top of ruby-marc (http://rubyforge.org/projects/marc) to help parse MARC records more easily and conveniently.
1
+ Enhanced MARC is a set of classes, modules and methods that sit on top of ruby-marc (http://rubyforge.org/projects/marc) to help parse the contents of MARC records more easily and conveniently.
2
2
  Installation:
3
3
  gem sources -a http://gems.github.com
4
- sudo gem install rsinger-enhanced-marc
4
+ sudo gem install rsinger-enhanced_marc
5
5
 
6
6
  Usage:
7
7
 
data/Rakefile CHANGED
@@ -21,3 +21,20 @@ Rake::RDocTask.new('doc') do |rd|
21
21
  rd.main = 'MARC::Record'
22
22
  rd.rdoc_dir = 'doc'
23
23
  end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |s|
28
+
29
+ s.add_dependency('marc')
30
+ s.name = 'enhanced_marc'
31
+ s.author = 'Ross Singer'
32
+ s.email = 'rossfsinger@gmail.com'
33
+ s.homepage = 'http://github.com/rsinger/enhanced-marc/tree'
34
+ s.summary = 'A DSL for MARC data'
35
+ s.description = 'A set of enhancements to ruby-marc to make parsing MARC data easier'
36
+ end
37
+ rescue LoadError
38
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
39
+ end
40
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
Binary file
@@ -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 BookRecord < Record
7
+
8
+ def initialize
9
+ super
10
+ @leader[6] = 'a' if @leader[6,1] == ' '
11
+ @leader[7] = 'm' if @leader[7,1] == ' '
12
+ @record_type = 'BKS'
13
+ @bibliographic_level = @leader.get_blvl
14
+ self.extend BookType
15
+ self.inspect_fixed_fields
16
+ end
17
+
18
+ def is_valid_type?
19
+ return false unless @leader[6,1].match(/[at]{1}/)
20
+ return true
21
+ end
22
+ def is_valid_blvl?
23
+ return false unless @leader[7,1].match(/[acdm]{1}/)
24
+ return true
25
+ end
26
+ def self.new_from_record(record)
27
+ rec = BookRecord.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,86 @@
1
+ module BookType
2
+ include RecordType
3
+ public :is_govdoc?, :nature_of_contents, :is_conference?, :audience_level, :form, :has_index?
4
+ # Checks the leader and any 006 fields to
5
+ # determine if the record is a manuscript.
6
+ # Returns a boolean.
7
+ def is_manuscript?
8
+ return true if @leader[6,1] == 't'
9
+ @fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
10
+ return true if fxd_fld[0,1] == 't'
11
+ }
12
+ return false
13
+ end
14
+
15
+ def set_manuscript(value=false, field=nil)
16
+ if field
17
+ return Exception.new("Field is not an 006") unless field.tag == '006'
18
+ if value
19
+ field.value[0] = 't'
20
+ else
21
+ field.value[0] = 'a'
22
+ end
23
+ else
24
+ if value
25
+ @leader[6] = 't'
26
+ else
27
+ @leader[6] = 'a'
28
+ end
29
+ end
30
+ end
31
+
32
+ def literary_form(human_readable=false)
33
+ lit_map={'0'=>'Non-fiction', '1'=>'Fiction', 'c'=>'Comic',
34
+ 'd'=>'Drama', 'e'=>'Essay', 'f'=>'Novel', 'h'=>'Humor/satire', 'i'=>'Letter', 'j'=>'Short story',
35
+ 'm'=>'Mixed', 'p'=>'Poetry', 's'=>'Speech', 'u'=>'Unknown'}
36
+ human_readable = lit_map if human_readable
37
+ return self.field_parser({:match=>'BKS', :start=>33,:end=>1}, {:match=>/[at]{1}/, :start=>16,:end=>1}, human_readable)
38
+ end
39
+
40
+ def is_biography?(human_readable=false)
41
+ biog_map = {'a'=>'Autobiography', 'b'=>'Individual biography',
42
+ 'c'=>'Collective biography', 'd'=>'Contains biographical information'}
43
+ human_readable = lit_map if human_readable
44
+ return self.field_parser({:match=>'BKS', :start=>34,:end=>1}, {:match=>/[at]{1}/, :start=>17,:end=>1}, human_readable)
45
+ end
46
+
47
+ def is_festschrift?
48
+ return true if self['008'].value[30,1] == "1" and @record_type == "BKS"
49
+ @fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
50
+ next unless fxd_fld.value[0,1].match(/[at]{1}/) and fxd_fld.value[13,1] == "1"
51
+ return true
52
+ }
53
+ return false
54
+ end
55
+
56
+ def is_illustrated?(human_readable=false)
57
+ ills_map = {'a'=>'Illustrations','b'=>'Maps','c'=>'Portraits','d'=>'Charts',
58
+ 'e'=>'Plans', 'f'=>'Plates', 'g'=>'Music', 'h'=>'Facsimilies', 'i'=>'Coats of arms',
59
+ 'j'=>'Genealogical tables', 'k'=>'Forms', 'j'=>'Genealogical tables', 'k'=>'Forms', 'l'=>'Samples',
60
+ 'm'=>'Phonodisc', 'o'=>'Photographs', 'p'=>'Illuminations'}
61
+ contents = []
62
+ if self.record_type == 'BKS'
63
+ self['008'].value[18,4].split(//).each { | char |
64
+ next if char == " "
65
+ if human_readable
66
+ contents << ills_map[char]
67
+ else
68
+ contents << char
69
+ end
70
+ }
71
+ end
72
+ @fields.find_all {|f| ('006') === f.tag}.each { | fxd_fld |
73
+ next unless fxd_fld.value[0,1].match(/[at]{1}/)
74
+ fxd_fld.value[1,4].split(//).each { | char |
75
+ next if char == " "
76
+ if human_readable
77
+ contents << ills_map[char]
78
+ else
79
+ contents << char
80
+ end
81
+ }
82
+ }
83
+ return false if contents.empty?
84
+ return contents
85
+ end
86
+ 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 ComputerRecord < Record
7
+
8
+ def initialize
9
+ super
10
+ @leader[6] = 'm' if @leader[6,1] == ' '
11
+ @leader[7] = 'm' if @leader[7,1] == ' '
12
+ @record_type = 'COM'
13
+ @bibliographic_level = @leader.get_blvl
14
+ self.extend ComputerType
15
+ self.inspect_fixed_fields
16
+ end
17
+
18
+ def is_valid_type?
19
+ return false unless @leader[6,1].match('m')
20
+ return true
21
+ end
22
+ def is_valid_blvl?
23
+ return false unless @leader[7,1].match(/[abcdims]{1}/)
24
+ return true
25
+ end
26
+ def self.new_from_record(record)
27
+ rec = ComputerRecord.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,14 @@
1
+ module ComputerType
2
+ include RecordType
3
+ public :form, :audience_level, :is_govdoc?
4
+ def file_type(human_readable=false)
5
+ return false unless self.contains_type?("COM")
6
+ file_map = {'a'=>'Numeric data', 'b'=>'Computer program', 'c'=>'Representational',
7
+ 'd'=>'Document', 'e'=>'Bibliographic data', 'f'=>'Font', 'g'=>'Game',
8
+ 'h'=>'Sounds', 'i'=>'Interactive multimedia', 'j'=>'Online', 'm'=>'Combination',
9
+ 'u'=>'Unknown', 'z'=>'Other'}
10
+ human_readable = file_map if human_readable
11
+ return self.field_parser({:match=>'COM', :start=>26,:end=>1}, {:match=>'m', :start=>9,:end=>1}, human_readable)
12
+ end
13
+
14
+ end
@@ -0,0 +1,132 @@
1
+ module MARC
2
+
3
+ # A class for accessing the MARC Leader
4
+ class Leader < String
5
+ attr_reader :leader, :record_type, :bibliographic_level, :encoding_level, :fixed_fields
6
+ def initialize(leader)
7
+ super
8
+ # leader defaults:
9
+ # http://www.loc.gov/marc/bibliographic/ecbdldrd.html
10
+ self[10..11] = '22'
11
+ self[20..23] = '4500'
12
+ end
13
+
14
+ def parse_leader
15
+ self.get_type
16
+ self.get_blvl
17
+ self.get_elvl
18
+ end
19
+
20
+ def get_type_code
21
+ return self[6,1]
22
+ end
23
+
24
+ def get_blvl_code
25
+ return self[7,1]
26
+ end
27
+
28
+ def get_type
29
+ return @record_type = self.type_translator(self.get_type_code, self.get_blvl_code)
30
+ end
31
+
32
+ def is_archival?
33
+ return true if self[8,1] == 'a'
34
+ return false
35
+ end
36
+
37
+ def get_blvl
38
+ blvls = {
39
+ 'a'=>'Monographic component part',
40
+ 'b'=>'Serial component part',
41
+ 'c'=>'Collection',
42
+ 'd'=>'Subunit',
43
+ 'i'=>'Integrating resource',
44
+ 'm'=>'Monograph/Item',
45
+ 's'=>'Serial'
46
+ }
47
+ return @bibliographic_level = blvls[self.get_blvl_code]
48
+ end
49
+
50
+ def set_type(type)
51
+ if type.length == 1
52
+ translated_type = self.types(type)
53
+ raise ArgumentError, "Invalid Type" if translated_type.nil?
54
+ elsif type.length > 1
55
+ translated_type = type
56
+ type = self.types(type)
57
+ raise ArgumentError, "Invalid Type" if type.nil?
58
+ else
59
+ raise ArgumentError, "Invalid Type"
60
+ end
61
+ self[6] = type
62
+ end
63
+
64
+ def type_translator(type_code, blvl_code)
65
+ valid_types = ['a','t','g','k','r','o','p','e','f','c','d','i','j','m']
66
+ unless valid_types.index(type_code)
67
+ raise ArgumentError, "Invalid Type!"
68
+ return
69
+ end
70
+ rec_types = {
71
+ 'BKS' => { :type => /[at]{1}/, :blvl => /[acdm]{1}/ },
72
+ 'SER' => { :type => /[a]{1}/, :blvl => /[bs]{1}/ },
73
+ 'VIS' => { :type => /[gkro]{1}/, :blvl => /[abcdms]{1}/ },
74
+ 'MIX' => { :type => /[p]{1}/, :blvl => /[cd]{1}/ },
75
+ 'MAP' => { :type => /[ef]{1}/, :blvl => /[abcdms]{1}/ },
76
+ 'SCO' => { :type => /[cd]{1}/, :blvl => /[abcdms]{1}/ },
77
+ 'REC' => { :type => /[ij]{1}/, :blvl => /[abcdms]{1}/ },
78
+ 'COM' => { :type => /[m]{1}/, :blvl => /[abcdms]{1}/ }
79
+ }
80
+
81
+ rec_types.each_key { | type |
82
+ return type if type_code.match(rec_types[type][:type]) and blvl_code.match(rec_types[type][:blvl])
83
+ }
84
+ raise ArgumentError, "Invalid BLvl!"
85
+ return nil
86
+ end
87
+
88
+ def get_elvl_code
89
+ return self[17,1]
90
+ end
91
+
92
+ def get_elvl
93
+ elvls = {
94
+ ' '=>'Full',
95
+ '1'=>'Full, not examined',
96
+ '2'=>'Less-than-full',
97
+ '3'=>'Abbreviated',
98
+ '4'=>'Core',
99
+ '5'=>'Partial',
100
+ '7'=>'Minimal',
101
+ '8'=>'Prepublication',
102
+ 'I'=>'Full-level input by OCLC participants',
103
+ 'K'=>'Less-than-full input by OCLC participants',
104
+ 'L'=>'Full-level input added from a batch process',
105
+ 'M'=>'Less-than-full added from a batch process',
106
+ 'E'=>'System-identified MARC error in batchloaded record',
107
+ 'J'=>'Deleted record'
108
+ }
109
+ return @encoding_level = elvls[self.get_elvl_code]
110
+ end
111
+
112
+ def ELvl
113
+ self.get_elvl unless @encoding_level
114
+ return @encoding_level
115
+ end
116
+
117
+ def get_desc_code
118
+ return self[18,1]
119
+ end
120
+
121
+ def get_desc
122
+ codes = {' '=>'Non-ISBD', 'a'=>'AACR2', 'i'=>'ISBD', 'u'=>'Unknown'}
123
+ return @descriptive_cataloging_form = codes[self.get_desc_code]
124
+ end
125
+
126
+ def Desc
127
+ self.get_desc unless @descriptive_cataloging_form
128
+ return @descriptive_cataloging_form
129
+ end
130
+
131
+ end
132
+ end
@@ -0,0 +1,122 @@
1
+ def get_fixed_field_position
2
+ ff_pos = {
3
+ 'Ctry' => {
4
+ '008' => {
5
+ 'BKS' => {:start => 15, :len => 3, :def => ' ' },
6
+ 'SER' => {:start => 15, :len => 3, :def => ' ' },
7
+ 'VIS' => {:start => 15, :len => 3, :def => ' ' },
8
+ 'MIX' => {:start => 15, :len => 3, :def => ' ' },
9
+ 'MAP' => {:start => 15, :len => 3, :def => ' ' },
10
+ 'SCO' => {:start => 15, :len => 3, :def => ' ' },
11
+ 'REC' => {:start => 15, :len => 3, :def => ' ' },
12
+ 'COM' => {:start => 15, :len => 3, :def => ' ' }
13
+ }
14
+ },
15
+ 'Lang' => {
16
+ '008' => {
17
+ 'BKS' => {:start => 35, :len => 3, :def => ' ' },
18
+ 'SER' => {:start => 35, :len => 3, :def => ' ' },
19
+ 'VIS' => {:start => 35, :len => 3, :def => ' ' },
20
+ 'MIX' => {:start => 35, :len => 3, :def => ' ' },
21
+ 'MAP' => {:start => 35, :len => 3, :def => ' ' },
22
+ 'SCO' => {:start => 35, :len => 3, :def => ' ' },
23
+ 'REC' => {:start => 35, :len => 3, :def => ' ' },
24
+ 'COM' => {:start => 35, :len => 3, :def => ' ' }
25
+ }
26
+ },
27
+ 'MRec' => {
28
+ '008' => {
29
+ 'BKS' => {:start => 38, :len => 3, :def => ' ' },
30
+ 'SER' => {:start => 38, :len => 3, :def => ' ' },
31
+ 'VIS' => {:start => 38, :len => 3, :def => ' ' },
32
+ 'MIX' => {:start => 38, :len => 3, :def => ' ' },
33
+ 'MAP' => {:start => 38, :len => 3, :def => ' ' },
34
+ 'SCO' => {:start => 38, :len => 3, :def => ' ' },
35
+ 'REC' => {:start => 38, :len => 3, :def => ' ' },
36
+ 'COM' => {:start => 38, :len => 3, :def => ' ' }
37
+ }
38
+ },
39
+ 'DtSt' => {
40
+ '008' => {
41
+ 'BKS' => {:start => 6, :len => 1, :def => ' ' },
42
+ 'SER' => {:start => 6, :len => 1, :def => 'c' },
43
+ 'VIS' => {:start => 6, :len => 1, :def => ' ' },
44
+ 'MIX' => {:start => 6, :len => 1, :def => ' ' },
45
+ 'MAP' => {:start => 6, :len => 1, :def => ' ' },
46
+ 'SCO' => {:start => 6, :len => 1, :def => ' ' },
47
+ 'REC' => {:start => 6, :len => 1, :def => ' ' },
48
+ 'COM' => {:start => 6, :len => 1, :def => ' ' },
49
+ }
50
+ },
51
+ 'Type' => {
52
+ 'ldr' => {
53
+ 'BKS' => {:start => 6, :len => 1, :def => 'a' },
54
+ 'SER' => {:start => 6, :len => 1, :def => 'a' },
55
+ 'VIS' => {:start => 6, :len => 1, :def => 'g' },
56
+ 'MIX' => {:start => 6, :len => 1, :def => 'p' },
57
+ 'MAP' => {:start => 6, :len => 1, :def => 'e' },
58
+ 'SCO' => {:start => 6, :len => 1, :def => 'c' },
59
+ 'REC' => {:start => 6, :len => 1, :def => 'i' },
60
+ 'COM' => {:start => 6, :len => 1, :def => 'm' },
61
+ }
62
+ },
63
+ 'Ctrl' => {
64
+ 'ldr' => {
65
+ 'BKS' => {:start => 8, :len => 1, :def => ' ' },
66
+ 'SER' => {:start => 8, :len => 1, :def => ' ' },
67
+ 'VIS' => {:start => 8, :len => 1, :def => ' ' },
68
+ 'MIX' => {:start => 8, :len => 1, :def => ' ' },
69
+ 'MAP' => {:start => 8, :len => 1, :def => ' ' },
70
+ 'SCO' => {:start => 8, :len => 1, :def => ' ' },
71
+ 'REC' => {:start => 8, :len => 1, :def => ' ' },
72
+ 'COM' => {:start => 8, :len => 1, :def => ' ' },
73
+ }
74
+ },
75
+ 'BLvl' => {
76
+ 'ldr'=> {
77
+ 'BKS' => {:start => 7, :len => 1, :def => 'm' },
78
+ 'SER' => {:start => 7, :len => 1, :def => 's' },
79
+ 'VIS' => {:start => 7, :len => 1, :def => 'm' },
80
+ 'MIX' => {:start => 7, :len => 1, :def => 'c' },
81
+ 'MAP' => {:start => 7, :len => 1, :def => 'm' },
82
+ 'SCO' => {:start => 7, :len => 1, :def => 'm' },
83
+ 'REC' => {:start => 7, :len => 1, :def => 'm' },
84
+ 'COM' => {:start => 7, :len => 1, :def => 'm' },
85
+ }
86
+ },
87
+ 'Desc' => {
88
+ 'ldr' => {
89
+ 'BKS' => {:start => 18, :len => 1, :def => ' ' },
90
+ 'SER' => {:start => 18, :len => 1, :def => ' ' },
91
+ 'VIS' => {:start => 18, :len => 1, :def => ' ' },
92
+ 'MIX' => {:start => 18, :len => 1, :def => ' ' },
93
+ 'MAP' => {:start => 18, :len => 1, :def => ' ' },
94
+ 'SCO' => {:start => 18, :len => 1, :def => ' ' },
95
+ 'REC' => {:start => 18, :len => 1, :def => ' ' },
96
+ 'COM' => {:start => 18, :len => 1, :def => ' ' },
97
+ }
98
+ },
99
+ 'ELvl' => {
100
+ 'ldr' => {
101
+ 'BKS' => {:start => 17, :len => 1, :def => ' ' },
102
+ 'SER' => {:start => 17, :len => 1, :def => ' ' },
103
+ 'VIS' => {:start => 17, :len => 1, :def => ' ' },
104
+ 'MIX' => {:start => 17, :len => 1, :def => ' ' },
105
+ 'MAP' => {:start => 17, :len => 1, :def => ' ' },
106
+ 'SCO' => {:start => 17, :len => 1, :def => ' ' },
107
+ 'REC' => {:start => 17, :len => 1, :def => ' ' },
108
+ 'COM' => {:start => 17, :len => 1, :def => ' ' },
109
+ }
110
+ },
111
+ 'TMat' => {
112
+ '008' => {
113
+ 'VIS' => {:start => 33, :len => 1, :def => ' ' },
114
+ },
115
+ '006' => {
116
+ 'VIS' => {:start => 16, :len => 1, :def => ' ' },
117
+ }
118
+ },
119
+ }
120
+
121
+
122
+ end