mods should return a hashref
[migration-tools.git] / Equinox-Migration / lib / Equinox / Migration / SubfieldMapper.pm
index ae33db0..8ba8892 100644 (file)
@@ -9,11 +9,11 @@ Equinox::Migration::SubfieldMapper - Generate named-field to MARC tag map from f
 
 =head1 VERSION
 
-Version 1.000
+Version 1.001
 
 =cut
 
-our $VERSION = '1.000';
+our $VERSION = '1.001';
 
 
 =head1 SYNOPSIS
@@ -36,8 +36,7 @@ or
     }
 
 
-=head1 ROUTINES
-
+=head1 METHODS
 
 =head2 new
 
@@ -55,6 +54,13 @@ sub new {
                        fields => {},
                        tags   => {} }, $class;
 
+    if ($args{mods}) {
+        die "Argument 'mods' is wrong type\n"
+          unless (ref $args{mods} eq "ARRAY");
+        for my $mod ( @{$args{mods}} )
+          { $self->{conf}{mods}{$mod} = 1 }
+    }
+
     if ($args{file}) {
         if (-r $args{file}) {
             $self->{conf}{file} = $args{file};
@@ -64,13 +70,6 @@ sub new {
         }
     }
 
-    if ($args{mods}) {
-        die "Argument 'mods' is wrong type\n"
-          unless (ref $args{mods} eq "ARRAY");
-        for my $mod ( @{$args{mods}} )
-          { $self->{conf}{mods}{$mod} = 1 }
-    }
-
     return $self;
 }
 
@@ -116,6 +115,44 @@ sub has {
     }
 }
 
+=head2 tags
+
+Returns an arrayref containing the tags defined in the map.
+
+    my $tags = $sfm->tags;
+    for my tag ( @{$tags} ) {
+        my $subs = $sfm->subfields($tag);
+        ...
+    }
+
+=cut
+
+sub tags {
+    my ($self) = @_;
+    return [ keys %{$self->{tags}} ];
+}
+
+=head2 subfields
+
+Given a tag, return an arrayref of the subfields mapped with that tag.
+
+    my $tags = $sfm->tags;
+    for my tag ( @{$tags} ) {
+        my $subs = $sfm->subfields($tag);
+        ...
+    }
+
+Returns C<undef> if C<tag> is not mapped.
+
+=cut
+
+sub subfields {
+    my ($self, $tag) = @_;
+    return undef unless $self->has($tag);
+    return [ keys %{$self->{tags}{$tag}} ];
+}
+
+
 =head2 field
 
 Given a tag and subfield code,
@@ -139,7 +176,7 @@ Returns the modifiers set on a mapping.
 
     $self->mods('fieldname')
 
-If there are no modifiers, C<undef> will be returned. Else a listref
+If there are no modifiers, C<undef> will be returned. Else a hashref
 will be returned.
 
 =cut
@@ -167,7 +204,9 @@ sub filters {
     return $self->{fields}{$field}{filt};
 }
 
+=head1 MAP CONSTRUCTION METHODS
 
+These methods are not generally accessed from user code.
 
 =head2 generate
 
@@ -189,8 +228,15 @@ sub generate {
         my $map = { mods => [], filt => [] };
         $map->{field} = shift @tokens;
         $map->{tag}   = shift @tokens;
-        for my $tok (@tokens) {
+        while (my $tok = shift @tokens) {
             last if ($tok =~ m/^#/);
+            if ($tok =~ m/^[a-z]:'/) {
+                $tok .= ' ' . shift @tokens
+                  until ($tokens[0] =~ m/'$/);
+                $tok .= ' ' . shift @tokens;
+                $tok =~ s/'//;
+                $tok =~ s/'$//;
+            }
             if ($tok =~ m/^m:/)
               { push @{$map->{mods}}, $tok }
             elsif ($tok =~ m/^f:/)
@@ -225,11 +271,18 @@ sub add {
     my ($self, $map) = @_;
 
     # trim the mods and filters
-    my $mods = []; my $filt = [];
-    for my $m (@{$map->{mods}})
-      { $m =~ s/^m://; push @{$mods}, $m }
-    for my $f (@{$map->{filt}})
-      { $f =~ s/^f://; push @{$filt}, $f }
+    my $mods = {};
+    my $filt = []; my %filt = ();
+    for my $m (@{$map->{mods}}) {
+        die "Modifier collision '$m' at line $." if $mods->{$m};
+        $m =~ s/^m://;
+        $mods->{$m} = 1;
+    }
+    for my $f (@{$map->{filt}}) {
+        die "Modifier collision '$f' at line $." if $filt{$f};
+        $f =~ s/^f://;
+        push @{$filt}, $f; $filt{$f} = 1;
+    }
     $map->{mods} = $mods;
     $map->{filt} = $filt;