File Coverage

blib/lib/SeeAlso/Identifier/PND.pm
Criterion Covered Total %
statement 20 20 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 26 26 100.0


line stmt bran cond sub pod time code
1             package SeeAlso::Identifier::PND;
2 6     6   161923 use strict;
  6         17  
  6         289  
3 6     6   32 use warnings;
  6         14  
  6         325  
4              
5             BEGIN {
6 6     6   32 use Exporter ();
  6         18  
  6         135  
7 6     6   31 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  6         11  
  6         898  
8 6     6   15 $VERSION = '0.61';
9 6         144 @ISA = qw(Exporter);
10             #Give a hoot don't pollute, do not export more than needed by default
11 6         13 @EXPORT = qw();
12 6         12 @EXPORT_OK = qw();
13 6         133 %EXPORT_TAGS = ();
14             }
15              
16 6     6   31 use base qw( SeeAlso::Identifier::GND );
  6         10  
  6         11280  
17             #use Carp;
18              
19             #################### subroutine header end ####################
20              
21              
22             =head1 NAME
23              
24             SeeAlso::Identifier::PND - SeeAlso handling of PND Numbers (Personennormdatei)
25              
26              
27             =head1 SYNOPSIS
28              
29             my $pnd = new SeeAlso::Identifier::PND "";
30              
31             print "invalid/empty" unless $pnd; # $pnd is defined but false !
32              
33             $pnd->value( '101115658X' );
34             $pnd->value( 'PND:101115658X' );
35             $pnd->value( '(DE-588)101115658X' );
36             $pnd->value( '(DE-588a)101115658X' );
37             $pnd->value( 'http://d-nb.info/gnd/101115658X' );
38             $pnd->value; # '' or PND identifier again (101115658X)
39             $pnd; # PND identifier as URI (http://d-nb.info/gnd/101115658X)
40              
41             $pnd->canonical; # http://d-nb.info/gnd/101115658X
42              
43             $pnd->pretty; # '' or PND identifier again (101115658X)
44              
45             =head1 DESCRIPTION
46              
47             This module handles identification numbers of the former Personennormdatei (PND)
48             of the German National Library (DNB). These continue to be valid identification
49             numbers of the successor Gemeinsame Normdatei (GND).
50              
51             The constructor of SeeAlso::Identifier::PND always returns an defined identifier
52             with all methods provided by L.
53             As canonical form the URN representation of PND with prefix C
54             is used (these HTTP URIs actually resolve).
55             As hashed and "pretty" form of an PND number, the number itself is used (including check digit).
56              
57             The authority files PND, GKD and SWD have been combined to the GND (Gemeinsame
58             Norm-Datei) in early 2012, the identifiers of "legacy" records however will
59             remain valid. They already are distinct and as such the parent module
60             L handles them simultaneously. As of v0.57
61             SeeAlso::Identifier::GND is lacking support for 10-digit identifiers and
62             does not implement all possible constraints (e.g. there are conflicting
63             checksum algorithms but by looking at the identifier you can not always
64             determine the authority file it belongs to and therefore there is no
65             certainity about the correct checksum).
66              
67             This module SeeAlso::Identifier::PND does not support the legacy GND numbers
68             for former entries of GKD and SWD and therefore its realm continues to be
69             restricted to authority records for persons and names (Tn and Tp) within
70             the GND.
71              
72             For compatibility reasons with SeeAlso::Identifier::GND the objects of this
73             module are implemented as blessed hashes instead of blessed scalars as
74             they would be by inheritance from SeeAlso::Identifier.
75              
76             =head1 METHODS
77              
78             =head2 parse ( $value )
79              
80             Get and/or set the value of the PND identifier. Returns an empty string or a possibly valid PND number. You can also use this method as function.
81              
82             Older numbers begin with "10" to "16" and have 8 digits plus check digit (which might be "X"),
83             More recently (since April 2011) assigned numbers have 9 digits plus check digit(0-X) and currently begin with "10".
84              
85             Although there is no official form known which notates PND numbers with dash(es),
86             their input is permitted, also prefixes "PND", "PND " and the likes.
87              
88             =cut
89              
90             sub parse {
91             local($_) = shift;
92             $_ = shift if ref($_) and scalar @_;
93              
94             return "" unless defined $_;
95              
96             s/\s+//g; # no kind of spaces makes sense in input data
97             s=^(?:http://d-nb.info/gnd/|[GP]ND[:/-]*\s?|\(DE-588[a]?\))([0-9xX-]+)=$1=i;
98              
99             s/^0+//;
100             tr/x-/X/d;
101              
102             return "" unless /^10?\d{7}[\dX]$/;
103              
104             return $_;
105             }
106              
107              
108             =head2 value ( [$value] )
109              
110             get/set using parse, not parent's method
111              
112             =cut
113              
114             sub value {
115             my($self, $value) = @_;
116             $self->{value} = $self->parse($value) if defined $value;
117             return $self->{value};
118             }
119              
120              
121             =head2 valid
122              
123             Performs checksum calculation for already parsed PND numbers.
124              
125             The mod-11-checksum is constructed the same way as for the "PICA PPN" (Pica Production Number
126             of the German National Library (PND identifiers acutally are PICA PPNs).
127              
128             =cut
129              
130             sub valid {
131             return undef unless $_[0]->{value} and $_[0]->{value} =~ /^10?\d{7}[\dX]$/;
132             my @i = reverse split(//, $_[0]->{value});
133             $i[0] = 10 if $i[0] =~ /X/i;
134              
135             my ($z, $w) = (0, 1);
136             foreach ( @i ) {
137             $z += ($_ * $w++)};
138             return ($z % 11) == 0;
139             }
140              
141              
142             =head2 hash ( [$value] )
143              
144             Sets and/or gets a form of the identifier suitable for processing.
145             In this class this will yield the same form as "parse", provided
146             it passes the "valid" test(s).
147              
148             =cut
149              
150             sub hash {
151             my $self = shift @_;
152             if ( defined $_[0] ) {
153             if ( $_[0] =~ /^10?\d{7}[\dXx]$/ ) {
154             $self->value($_[0])}
155             else {
156             return $self->{value} = undef}
157             }
158             return $self->valid ? $self->{value} : "";
159             }
160              
161              
162             =head2 indexed ( [$value] )
163              
164             This is only since the parent class L as of v0.57
165             is not compliant to the interfaces specified by L
166             with respect to "indexed" being an alias for "hash".
167              
168             =cut
169              
170             sub indexed {
171             my $self = shift @_;
172             return $self->hash;
173             }
174              
175              
176             =head2 canonical ( [$value] )
177              
178             Yields the (for SeeAlso) canonical form of the identifier (if valid) as
179             an URI.
180              
181             =cut
182              
183             sub canonical {
184             my $self = shift @_;
185             if ( defined $_[0] ) {
186             if ( $_[0] =~ m=^http://d-nb.info/gnd/= ) {
187             $self->value($_[0])}
188             else {
189             return $self->{value} = undef}
190             }
191             return $self->valid ? ("http://d-nb.info/gnd/" . $self->{value}) : "";
192             }
193              
194              
195             =head2 normalized ( [$value] )
196              
197             This is only since the parent class L as of v0.57
198             is not compliant to the interfaces specified by L
199             with respect to "normalized" being an alias for "canonical".
200              
201             =cut
202              
203             sub normalized {
204             my $self = shift @_;
205             return $self->canonical;
206             }
207              
208              
209             =head2 cmp ( $value )
210              
211             For comparisons a "numerical" order is established by left-padding
212             the identifiers with sufficiently many zeroes.
213              
214             =cut
215              
216             sub cmp {
217             my $self = shift;
218             my $string1 = sprintf("%010s", $self->{value});
219             my $class = ref($self);
220             my $second = shift;
221             my $string2 = sprintf("%010s", $class->new($second)->{value});
222             return $string1 cmp $string2;
223             }
224              
225              
226             =head2 pretty
227              
228             Try to give the most official form of the identifier.
229              
230             =cut
231              
232             sub pretty {
233             my $self = shift @_;
234             return $self->valid ? $self->{value} : "";
235             }
236              
237              
238             =head1 AUTHOR
239              
240             Thomas Berger C<< >>
241              
242             =head1 ACKNOWLEDGEMENTS
243              
244             Jakob Voss C<< >> crafted SeeAlso::Identifier::GND.
245              
246             =head1 COPYRIGHT
247              
248             This program is free software; you can redistribute
249             it and/or modify it under the same terms as Perl itself.
250              
251             The full text of the license can be found in the
252             LICENSE file included with this module.
253              
254              
255             =head1 SEE ALSO
256              
257             perl(1), L.
258              
259             =cut
260              
261             #################### main pod documentation end ###################
262              
263              
264             1;
265             # The preceding line will help the module return a true value
266