1 package Equinox::Migration::SubfieldMapper;
8 Equinox::Migration::SubfieldMapper - Generate named-field to MARC tag map from file
16 our $VERSION = '1.000';
21 Using a file as input, E::M::SM generates a mapping of MARC subfields
22 to arbitrary field names, and provides several access mechanisms to
25 use Equinox::Migration::SubfieldMapper;
27 my $stl = Equinox::Migration::SubfieldMapper->new( file => ".txt" );
28 my $tags = $stl->as_hashref;
32 my $stl = Equinox::Migration::SubfieldMapper->new( file => ".txt" );
33 if ( $stl->has($foo) ) {
34 # if $foo is an element of $stl's parsed list
44 Takes one optional argument, C<file>. If this is speficied, the tag
45 list will be populated as per that file on instantiation.
47 Returns a E::M::STL object.
52 my ($class, %args) = @_;
54 my $self = bless { conf => { mods => undef },
60 $self->{conf}{file} = $args{file};
63 die "Can't open file: $!\n";
68 die "Argument 'mods' is wrong type\n"
69 unless (ref $args{mods} eq "ARRAY");
70 for my $mod ( @{$args{mods}} )
71 { $self->{conf}{mods}{$mod} = 1 }
79 Ask it whether your mapping has various things, and it'll let you know.
81 $sm->has('fieldname') # is this fieldname mapped?
82 $sm->has(901) # are there any mappings for this tag?
83 $sm->has(650,'c') # is this tag/subfield combo mapped?
84 $sm->has('name', 245, 'a') # is this name mapped to 245$a?
86 Returns 1 if true, 0 if false.
88 FIXME: use named params instead of positional
93 my ($self, @chunks) = @_;
94 return undef unless (defined $chunks[0]);
96 if ($chunks[0] =~ /^\d/) {
97 if (defined $chunks[1]) {
98 return 1 if ( defined $self->{tags}{$chunks[0]}{$chunks[1]} );
101 return 1 if ( defined $self->{tags}{$chunks[0]} );
105 if (defined $chunks[2]) {
106 return 1 if ( $self->{fields}{$chunks[0]}{tag} eq $chunks[1] and
107 $self->{fields}{$chunks[0]}{sub} eq $chunks[2] );
109 } elsif (defined $chunks[1]) {
110 return 1 if ( $self->{fields}{$chunks[0]}{tag} eq $chunks[1] );
113 return 1 if ( defined $self->{fields}{$chunks[0]} );
121 Given a tag and subfield code,
123 my $fname = $sm->field(945, 'p')
125 return the name mapped to them. Returns C<undef> if no mapping exists.
130 my ($self, $tag, $sub) = @_;
131 return undef unless (defined $tag and defined $sub);
132 return undef unless $self->has($tag, $sub);
133 return $self->{tags}{$tag}{$sub};
138 Returns the modifiers set on a mapping.
140 $self->mods('fieldname')
142 If there are no modifiers, C<undef> will be returned. Else a listref
148 my ($self, $field) = @_;
149 return undef unless $self->has($field);
150 return $self->{fields}{$field}{mods};
155 Returns the content filters set on a mapping
157 $self->filters('fieldname')
159 If there are no filters, C<undef> will be returned. Else a listref
165 my ($self, $field) = @_;
166 return undef unless $self->has($field);
167 return $self->{fields}{$field}{filt};
174 Generate initial mapping from file.
179 my ($self, $file) = @_;
181 open TAGFILE, '<', $self->{conf}{file};
187 my @tokens = split /\s+/;
189 my $map = { mods => [], filt => [] };
190 $map->{field} = shift @tokens;
191 $map->{tag} = shift @tokens;
192 while (my $tok = shift @tokens) {
193 last if ($tok =~ m/^#/);
194 if ($tok =~ m/^[a-z]:'/) {
195 $tok .= ' ' . shift @tokens
196 until ($tokens[0] =~ m/'$/);
197 $tok .= ' ' . shift @tokens;
202 { push @{$map->{mods}}, $tok }
203 elsif ($tok =~ m/^f:/)
204 { push @{$map->{filt}}, $tok }
205 elsif ($tok =~ m/^[a-z0-9]$/)
206 { $map->{sub} = $tok }
208 { die "Unknown chunk '$tok' at line $.\n" }
216 Add new item to mapping. Not usually called directly from user code.
220 Where C<$map> is a hashref that, at a minimum, looks like
222 { field => "value", tag => NNN, sub => X }
224 and may also have the key/value pairs
232 my ($self, $map) = @_;
234 # trim the mods and filters
235 my $mods = []; my $filt = [];
236 for my $m (@{$map->{mods}})
237 { $m =~ s/^m://; push @{$mods}, $m }
238 for my $f (@{$map->{filt}})
239 { $f =~ s/^f://; push @{$filt}, $f }
240 $map->{mods} = $mods;
241 $map->{filt} = $filt;
243 # check bits for validity
244 $self->validate($map);
246 # add data to the fields hash
247 $self->{fields}{ $map->{field} } = { tag => $map->{tag},
249 mods => $map->{mods},
252 # and to the tags hash
253 $self->{tags}{ $map->{tag} }{ $map->{sub} } = $map->{field};
258 Passed a reference to the hash given to C<add>, validate scans its
259 contents for common errors and dies if there is an issue.
261 * field, tag, and sub are required
262 * fieldnames must start with a letter
263 * fieldnames must be unique
264 * tag must be between 0 and 999
265 * subfield code must be a single alphanumeric character
266 * tag+subfield can only be mapped once
267 * if a list of allowable mod values was given in the call to
268 C<new>, any modifiers must be on that list
273 my ($self, $map) = @_;
275 $.= 1 unless defined $.;
277 die "Required field missing (line $.)\n"
278 unless (defined $map->{field} and defined $map->{tag} and defined $map->{sub});
280 die "Fieldnames must start with letter (line $.)\n"
281 unless ($map->{field} =~ /^[a-zA-z]/);
283 die "Invalid tag (line $.)\n"
284 if ($map->{tag} =~ /[^\d\-]/ or $map->{tag} < 0 or $map->{tag} > 999);
286 die "Invalid subfield code (line $.)\n"
287 if (length $map->{sub} != 1 or $map->{sub} =~ /[^a-zA-Z0-9]/);
289 # test mod names if we have a set to check against
290 if (defined $self->{conf}{mods}) {
291 for my $mod ( @{$map->{mods}} ) {
292 die "Modifier '$mod' not allowed\n"
293 unless $self->{conf}{mods}{$mod};
297 die "Fieldnames must be unique (line $.)\n"
298 if (defined $self->{fields}{$map->{field}});
300 die "Subfields cannot be mapped twice (line $.)\n"
301 if (defined $self->{tags}{$map->{tag}}{$map->{sub}});
308 Shawn Boyette, C<< <sboyette at esilibrary.com> >>
312 Please report any bugs or feature requests to the above email address.
316 You can find documentation for this module with the perldoc command.
318 perldoc Equinox::Migration::SubfieldMapper
321 =head1 COPYRIGHT & LICENSE
323 Copyright 2009 Equinox, all rights reserved.
325 This program is free software; you can redistribute it and/or modify it
326 under the same terms as Perl itself.
331 1; # End of Equinox::Migration::SimpleTagList