lib/marcspec/marcfieldspec.rb in marcspec-0.6.0 vs lib/marcspec/marcfieldspec.rb in marcspec-0.7.0

- old
+ new

@@ -1,207 +1,3 @@ -require 'marc4j4r' -require 'set' -require 'pp' -module MARCSpec - - # A ControlFieldSpec takes a control tag (generally 001..009) and an optional zero-based range - # When called with marc_values(record), it returns either the complete value of all - # occurances of the field in question (in the order they appear in the record), or - # the zero-based substrings based on the passed range. - # - # @example Get the whole 001 - # cfs = MARCSpec::ControlTagSpec.new('001') - # - # @example Get the first three characters of the 008 - # cfs = MARCSpec::ControlTagSpec.new('001', 0..2) - # - # Note that the use of the zero-based range in this manner conforms to the way MARC - # substrings are specified. - - class ControlFieldSpec - attr_accessor :tag, :range - - def initialize (tag, range=nil) - unless MARC4J4R::ControlField.control_tag? tag - raise ArgumentError "Tag must be a control tag" - end - @tag = tag - self.range = range - end - - def == other - return ((self.tag == other.tag) and - (self.range = other.range)) - end - - - # Always force a real range, since in Ruby 1.9 a string subscript with a single fixnum - # will return the character code of that character (e.g., "Bill"[0] => 66, wherease - # "Bill"[0..0] gives the expected 'B' - # - # @param [nil, Fixnum, Range] range A zero-based substring range or character position - # @return [MARCSpec::ControlFieldSpec] self - - def range= range - if range.nil? - @range = nil - return self - end - if range.is_a? Fixnum - if range < 0 - raise ArgumentError, "Range must be nil, an integer offset (1-based), or a Range, not #{range}" - end - - @range = range..range - - elsif range.is_a? Range - @range = range - else - raise ArgumentError, "Range must be nil, an integer offset (1-based), or a Range, not #{range.inspect}" - end - return self - end - - - def marc_values r - vals = r.find_by_tag(@tag).map {|f| f.value} - if @range - return vals.map {|v| v[@range]} - else - return vals - end - end - - def pretty_print pp - pp.pp eval(self.asPPString) - end - - def asPPString - s = StringIO.new - if @range - PP.pp([@tag, @range], s) - else - PP.pp([@tag], s) - end - return s.string - end - - def self.fromPPString str - a = eval(str) - return self.new(*a) - end - - end - - - # A LeaderSpec deals only with the leader. It's basically the same as a controlfield spec, but - # using the string 'LDR' to identify itself - - class LeaderSpec < ControlFieldSpec - - # Built to be syntax-compatible with ControlFieldSpec, the tag must always - # be 'LDR' (case matters) - # - # @param ['LDR'] tag The 'tag'; in this case, always 'LDR' - # @param [Fixnum, Range<Fixnum>] range substring specification (either one character or a range) to return - # instead of the whole leader. - - def initialize (tag, range=nil) - unless tag == 'LDR' - raise ArgumentError "Tag must be 'LDR'" - end - @tag = 'LDR' - self.range = range - end - - # Return the appropriate value (either the leader or a subset of it) from the - # given record - # - # @param [MARC4J4R::Record] r A MARC4J4R Record - # @return [String] the leader or substring of the leader - def marc_values r - if @range - return r.leader[@range] - else - return r.leader - end - end - end - - - # A VariableFieldSpec has a tag (three chars) and a set of codes. Its #marc_values(r) method will return - # all the values for the subfields for the given codes joined by the optional joiner (space by default) - # - # The subfield values are presented in the order they appear in the document, *not* the order the subfield - # codes are specified - # - # @example Get the $a from the 245s - # vfs = MARCSpec::VariableFieldSpec.new('245', 'a') - # - # vfs = MARCSpec::VariableFieldSpec.new('245', 'ab') - - - class VariableFieldSpec - - attr_accessor :tag, :codes, :joiner - - def initialize tag, codes=nil, joiner=' ' - @tag = tag - @joiner = joiner || ' ' - self.codes = codes - end - - def == other - return ((self.tag == other.tag) and - (self.codes = other.codes) and - (self.joiner = other.joiner)) - end - - def codes= c - if c.nil? - @codes = nil - return nil - end - - if( c.is_a? Array) or (c.is_a? Set) or (c.is_a? Range) - @codes = c.to_a - else - @codes = c.split(//) - end - - return @codes - end - - def marc_values r - fields = r.find_by_tag(@tag) - vals = [] - fields.each do |f| - subvals = f.sub_values(@codes) - subvals = subvals.join(@joiner) if subvals.size > 0 and (@codes.nil? or @codes.size > 1) - vals << subvals - end - vals.flatten! - return vals - end - - def pretty_print pp - pp.pp eval(self.asPPString) - end - - def asPPString - s = StringIO.new - if @joiner and @joiner != ' ' - PP.pp([@tag, '*', '*', @codes.join(''), @joiner], s) - else - PP.pp([@tag, '*', '*', @codes.join('')], s) - end - return s.string - end - - def self.fromPPString str - a = eval(str) - return self.new(a[0], a[3], a[4]) - end - - end - -end +require 'marcspec/controlfieldspec'; +require 'marcspec/variablefieldspec'; +require 'marcspec/leaderspec';