=head1 VERSION
-Version 1.000
+Version 1.005
=cut
-our $VERSION = '1.000';
+our $VERSION = '1.005';
=head1 SYNOPSIS
that set.
use Equinox::Migration::SubfieldMapper;
-
- my $stl = Equinox::Migration::SubfieldMapper->new( file => ".txt" );
- my $tags = $stl->as_hashref;
+ ...
-or
-
- my $stl = Equinox::Migration::SubfieldMapper->new( file => ".txt" );
- if ( $stl->has($foo) ) {
- # if $foo is an element of $stl's parsed list
- # do stuff ...
- }
-
-
-=head1 ROUTINES
+=head1 METHODS
=head2 new
Takes one optional argument, C<file>. If this is speficied, the tag
list will be populated as per that file on instantiation.
-Returns a E::M::STL object.
+Returns a E::M::SM object.
=cut
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};
}
}
- 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;
}
}
}
+=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,
=head2 mods
-Returns the modifiers set on a mapping.
+With no argument, returns a hashref containing all modifiers for the entire map:
+
+ {
+ modifier => {
+ tag => [ list_of subs ],
+ ...
+ },
+ ...
+ }
+
+Given a fieldname, returns a hashref of the modifiers set on that mapping.
$self->mods('fieldname')
-If there are no modifiers, C<undef> will be returned. Else a listref
-will be returned.
+Returns undef is nothing is defined.
=cut
sub mods {
my ($self, $field) = @_;
+ return $self->{allmods} unless defined $field;
return undef unless $self->has($field);
+ return undef unless (%{ $self->{fields}{$field}{mods} });
return $self->{fields}{$field}{mods};
}
sub filters {
my ($self, $field) = @_;
return undef unless $self->has($field);
+ return undef unless ($self->{fields}{$field}{filt});
return $self->{fields}{$field}{filt};
}
+=head2 sep
+
+Returns the separator string set on a mapping. Used only
+if concatenating.
+
+=cut
+
+sub sep {
+ my ($self, $field) = @_;
+ return undef unless $self->has($field);
+ return $self->{fields}{$field}{sep};
+}
+
+=head1 MAP CONSTRUCTION METHODS
+These methods are not generally accessed from user code.
=head2 generate
chomp;
my @tokens = split /\s+/;
- my $map = { mods => [], filt => [] };
+ my $map = { mods => [], filt => [], sep => ' ' };
$map->{field} = shift @tokens;
$map->{tag} = shift @tokens;
- while (my $tok = shift @tokens) {
+ while (defined (my $tok = shift @tokens)) {
last if ($tok =~ m/^#/);
- if ($tok =~ m/^[a-z]:'/) {
+ if ($tok =~ m/^[a-z]:'/ and $tok !~ /^'$/) {
$tok .= ' ' . shift @tokens
until ($tokens[0] =~ m/'$/);
$tok .= ' ' . shift @tokens;
{ push @{$map->{filt}}, $tok }
elsif ($tok =~ m/^[a-z0-9]$/)
{ $map->{sub} = $tok }
+ elsif ($tok =~ /^c:(.*)$/)
+ { $map->{sep} = $1 }
else
{ die "Unknown chunk '$tok' at line $.\n" }
}
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;
+ push @{$self->{allmods}{$m}{ $map->{tag} }}, $map->{sub};
+ }
+ for my $f (@{$map->{filt}}) {
+ die "Filter collision '$f' at line $." if $filt{$f};
+ $f =~ s/^f://;
+ push @{$filt}, $f; $filt{$f} = 1;
+ }
$map->{mods} = $mods;
$map->{filt} = $filt;
$self->{fields}{ $map->{field} } = { tag => $map->{tag},
sub => $map->{sub},
mods => $map->{mods},
- filt => $map->{filt}
+ filt => $map->{filt},
+ sep => $map->{sep},
};
# and to the tags hash
$self->{tags}{ $map->{tag} }{ $map->{sub} } = $map->{field};
# test mod names if we have a set to check against
if (defined $self->{conf}{mods}) {
- for my $mod ( @{$map->{mods}} ) {
+ for my $mod ( keys %{$map->{mods}} ) {
die "Modifier '$mod' not allowed\n"
unless $self->{conf}{mods}{$mod};
}