Changes 09
MANIFEST 16
META.json 66
META.yml 66
bin/checkdigits.pl 219
cgi-bin/checkdigits.cgi 210
lib/Algorithm/CheckDigits/M10_008.pm 55
lib/Algorithm/CheckDigits/M11_001.pm 01
lib/Algorithm/CheckDigits/M97_002.pm 86
lib/Algorithm/CheckDigits/MBase_003.pm 88
lib/Algorithm/CheckDigits/MXX_003.pm 55
lib/Algorithm/CheckDigits.pm 183351
t/PluginLibA.pm 073
t/PluginLibB.pm 087
t/plugina.t 022
t/pluginb-without.t 018
t/pluginb.t 023
t/valid.data 47
18 files changed (This is a version diff) 230662
@@ -1,5 +1,14 @@
 Revision history for Perl extension CheckDigits.
 
+1.2.1 Sun Mar  3 22:51:45 CET 2013
+	- changed list items in POD from 0, 1, ... to S<0>, S<1>, ...
+	  according to a thread on the perl5 porters list
+	  (www.nntp.perl.org/group/perl.perl5.porters/2013/02/msg199355.html)
+
+	  David Wheeler: "Lists must start with 1. When it saw the 0, it
+	  assumed it was a definition list, so the numbers after that
+	  don't look right."
+
 1.2.0 Fr 8. Jun 11:19:25 CEST 2012
 	- reworked Algorithm::CheckDigits::MXX_001.pm, added ABA routing
 	  numbers
@@ -49,6 +49,7 @@ lib/Algorithm/CheckDigits/MXX_005.pm
 lib/Algorithm/CheckDigits/MXX_006.pm
 Makefile.PL
 MANIFEST
+META.json
 META.yml
 README
 t/checkdigits.t
@@ -58,6 +59,11 @@ t/iban.t
 t/imei.t
 t/isbn13.t
 t/nip.t
+t/plugina.t
+t/pluginb-without.t
+t/pluginb.t
+t/PluginLibA.pm
+t/PluginLibB.pm
 t/pod-coverage.t
 t/pod.t
 t/script-checkdigits.t
@@ -65,4 +71,3 @@ t/sedol.t
 t/upc.t
 t/valid.data
 t/valid.t
-META.json
@@ -34,7 +34,7 @@
    "provides" : {
       "Algorithm::CheckDigits" : {
          "file" : "lib/Algorithm/CheckDigits.pm",
-         "version" : "v1.2.0"
+         "version" : "v1.3.0"
       },
       "Algorithm::CheckDigits::M07_001" : {
          "file" : "lib/Algorithm/CheckDigits/M07_001.pm",
@@ -70,7 +70,7 @@
       },
       "Algorithm::CheckDigits::M10_008" : {
          "file" : "lib/Algorithm/CheckDigits/M10_008.pm",
-         "version" : "v1.1.1"
+         "version" : "v1.2.1"
       },
       "Algorithm::CheckDigits::M10_009" : {
          "file" : "lib/Algorithm/CheckDigits/M10_009.pm",
@@ -170,7 +170,7 @@
       },
       "Algorithm::CheckDigits::M97_002" : {
          "file" : "lib/Algorithm/CheckDigits/M97_002.pm",
-         "version" : "0.53"
+         "version" : "v1.2.1"
       },
       "Algorithm::CheckDigits::MBase_001" : {
          "file" : "lib/Algorithm/CheckDigits/MBase_001.pm",
@@ -182,7 +182,7 @@
       },
       "Algorithm::CheckDigits::MBase_003" : {
          "file" : "lib/Algorithm/CheckDigits/MBase_003.pm",
-         "version" : "0.53"
+         "version" : "v1.2.1"
       },
       "Algorithm::CheckDigits::MXX_001" : {
          "file" : "lib/Algorithm/CheckDigits/MXX_001.pm",
@@ -194,7 +194,7 @@
       },
       "Algorithm::CheckDigits::MXX_003" : {
          "file" : "lib/Algorithm/CheckDigits/MXX_003.pm",
-         "version" : "v1.1.2"
+         "version" : "v1.2.1"
       },
       "Algorithm::CheckDigits::MXX_004" : {
          "file" : "lib/Algorithm/CheckDigits/MXX_004.pm",
@@ -215,5 +215,5 @@
          "http://dev.perl.org/licenses/"
       ]
    },
-   "version" : "v1.2.0"
+   "version" : "v1.3.0"
 }
@@ -17,7 +17,7 @@ name: Algorithm-CheckDigits
 provides:
   Algorithm::CheckDigits:
     file: lib/Algorithm/CheckDigits.pm
-    version: v1.2.0
+    version: v1.3.0
   Algorithm::CheckDigits::M07_001:
     file: lib/Algorithm/CheckDigits/M07_001.pm
     version: 0.53
@@ -44,7 +44,7 @@ provides:
     version: 0.53
   Algorithm::CheckDigits::M10_008:
     file: lib/Algorithm/CheckDigits/M10_008.pm
-    version: v1.1.1
+    version: v1.2.1
   Algorithm::CheckDigits::M10_009:
     file: lib/Algorithm/CheckDigits/M10_009.pm
     version: 0.53
@@ -119,7 +119,7 @@ provides:
     version: 0.53
   Algorithm::CheckDigits::M97_002:
     file: lib/Algorithm/CheckDigits/M97_002.pm
-    version: 0.53
+    version: v1.2.1
   Algorithm::CheckDigits::MBase_001:
     file: lib/Algorithm/CheckDigits/MBase_001.pm
     version: 0.53
@@ -128,7 +128,7 @@ provides:
     version: v1.1.2
   Algorithm::CheckDigits::MBase_003:
     file: lib/Algorithm/CheckDigits/MBase_003.pm
-    version: 0.53
+    version: v1.2.1
   Algorithm::CheckDigits::MXX_001:
     file: lib/Algorithm/CheckDigits/MXX_001.pm
     version: v1.2.0
@@ -137,7 +137,7 @@ provides:
     version: 0.53
   Algorithm::CheckDigits::MXX_003:
     file: lib/Algorithm/CheckDigits/MXX_003.pm
-    version: v1.1.2
+    version: v1.2.1
   Algorithm::CheckDigits::MXX_004:
     file: lib/Algorithm/CheckDigits/MXX_004.pm
     version: 0.53
@@ -151,4 +151,4 @@ requires:
   version: 0
 resources:
   license: http://dev.perl.org/licenses/
-version: v1.2.0
+version: v1.3.0
@@ -19,8 +19,16 @@ my $cmd = shift || 'check';
 pod2usage(0) unless $cmd;
 
 if ($cmd =~ /^list(_alg(orithms)?)?$/i) {
+    my %descr = Algorithm::CheckDigits::method_descriptions();
     for my $method (Algorithm::CheckDigits->method_list()) {
-        print $method, "\n";
+        print $method, ': ', $descr{$method}, "\n";
+    }
+    exit 0;
+}
+if ($cmd =~ /^descr(ibe)?$/i) {
+    while (my $method = shift @ARGV) {
+        print join(': ',Algorithm::CheckDigits->method_descriptions($method))
+            , "\n";
     }
     exit 0;
 }
@@ -93,6 +101,7 @@ This document describes checkdigits version 0.0.1
    checkdigit      - return checkdigit belonging to number
    complete        - return number completed with checkdigit
    list_algorithms - list all known algorithms
+   describe        - describe the given algorithms
 
 =head1 DESCRIPTION
 
@@ -123,9 +132,17 @@ compute any checkdigit.
 When called with this command, the program will take the number compute the
 appropriate checkdigits and return the complete number with checkdigits.
 
+=head3 describe
+
+Called with this command, the program will list the algorithm handles given on
+the command line with a short description or the word "unknown" for any
+unknown algorithm. See command I<list_algorithms> for a list of known
+algorithms.
+
 =head3 list_algorithms
 
-Called with this command, the program will list all known algorithms and exit.
+Called with this command, the program will list all known algorithms together
+with a short description and then exit.
 
 =head1 DIAGNOSTICS
 
@@ -11,6 +11,7 @@ my $algorithm = param('algorithm');
 my $number    = param('number');
 my $ok = '';
 my @all_algorithms;
+my %all_labels;
 
 if ($ENV{ALL_ALGORITHMS}) {
     @all_algorithms = split /,/, $ENV{ALL_ALGORITHMS};
@@ -19,6 +20,8 @@ else {
     @all_algorithms = Algorithm::CheckDigits::method_list();
 }
 
+%all_labels = Algorithm::CheckDigits::method_descriptions(@all_algorithms);
+
 if ($number and $algorithm) {
     my $cd = CheckDigits($algorithm);
     if ($cd->is_valid($number)) {
@@ -34,8 +37,13 @@ print header(),
       start_html(),
       start_form(),
       textfield('number'),
-      popup_menu('algorithm', \@all_algorithms),
+      popup_menu(-name   => 'algorithm',
+      		 -values => \@all_algorithms,
+		 -labels => \%all_labels),
       submit('check'),
       end_form(),
       $ok,
-      end_html();
+      end_html(),
+      "\n";
+
+exit 0;
@@ -5,7 +5,7 @@ use strict;
 use warnings;
 use integer;
 
-use version; our $VERSION = qv('1.1.1');
+use version; our $VERSION = qv('1.2.1');
 
 our @ISA = qw(Algorithm::CheckDigits);
 
@@ -139,23 +139,23 @@ numerical SEDOL codes issued prior to March 2004 remain valid.
 
 =over 4
 
-=item 0
+=item S<0>
 
 All characters are assigned a numerical value from 0 to 35 where the
 characters '0' to '9' get 0 to 9, 'B' to 'Z' get 11 to 35 with the
 position of the vowels kept empty (for instance 'D' gets 13, 'F' gets
 15). 
 
-=item 1
+=item S<1>
 
 Beginning left all numbers are weighted with 1,3,1,7,3,9 and 1
 (checkdigit)
 
-=item 2
+=item S<2>
 
 The sum of all products is computed.
 
-=item 3
+=item S<3>
 
 The check digit is the difference of the sum from step 3 to the next
 multiple of 10.
@@ -19,6 +19,7 @@ my $cd = {
 };
 
 $cd->{'issn'} = $cd->{'isbn'};
+$cd->{'vatrn_pt'} = $cd->{'ustid_pt'};
 
 sub new {
 	my $proto = shift;
@@ -6,9 +6,7 @@ use strict;
 use warnings;
 use integer;
 
-#use Math::BigInt;
-
-our $VERSION = '0.53';
+use version; our $VERSION = qv('1.2.1');
 
 our @ISA = qw(Algorithm::CheckDigits);
 
@@ -149,21 +147,21 @@ Account Number (IBAN)
 
 =over 4
 
-=item 0
+=item S<0>
 
 The IBAN number must be prepared. The first two letters and the
 checksum will be moved to the right end. The letters are substituted
 according to the substitute table and the checksum is set to '00'.
 
-=item 1
+=item S<1>
 
 The whole number is taken modulo 97.
 
-=item 2
+=item S<2>
 
-The checksum is difference between 98 and the sum of step 2.
+The checksum is difference between 98 and the result of step 1.
 
-=item 3
+=item S<3>
 
 If the checksum is smaller then 10, a leading zero will be
 prepended.
@@ -5,7 +5,7 @@ use strict;
 use warnings;
 use integer;
 
-our $VERSION = '0.53';
+use version; our $VERSION = qv('1.2.1');
 
 our @ISA = qw(Algorithm::CheckDigits);
 
@@ -137,33 +137,33 @@ and Contribution Identifier)
 
 =over 4
 
-=item 0
+=item S<0>
 
 In the string describing the number all letters (A-Z) are replaced
 with numbers 10-35 accordingly. All other non-numbers are replaced by
 36.
 
-=item 1
+=item S<1>
 
 Beginning right the numbers at all odd positions are added.
 
-=item 2
+=item S<2>
 
 The sum from step 1 is multiplied by 3.
 
-=item 3
+=item S<3>
 
 Beginning right the numbers at all even positions are added.
 
-=item 4
+=item S<4>
 
 The sums from step 2 and 3 are added.
 
-=item 5
+=item S<5>
 
 The sum from step 4 is taken modulo 37.
 
-=item 6
+=item S<6>
 
 The checksum is 37 minus the sum from step 5 where numbers from 10 to
 35 are represented by 'A' to 'Z' accordingly and 36 is represented by
@@ -5,7 +5,7 @@ use strict;
 use warnings;
 use integer;
 
-our $VERSION = '1.1.2';
+use version; our $VERSION = qv('1.2.1');
 
 our @ISA = qw(Algorithm::CheckDigits);
 
@@ -136,21 +136,21 @@ The algorithm is a variation of the Verhoeff scheme.
 
 =over 4
 
-=item 0
+=item S<0>
 
 All letters are changed to numbers.
 
-=item 1
+=item S<1>
 
 All digits are permutated according to a permutation table.
 
-=item 2
+=item S<2>
 
 The permutated digits are combined using a diëder table. The first
 with the second, the result with the third, this result with the
 fourth and so on.
 
-=item 3
+=item S<3>
 
 The result of the last combination in the diëder table is in such a
 way combined that the result is 0 (zero). The number used for this
@@ -21,156 +21,199 @@ our @ISA = qw(Exporter);
 our %EXPORT_TAGS = (
     'all' => [
         qw(
-          CheckDigits method_list print_methods
+          CheckDigits method_descriptions method_list print_methods
           ) ] );
 
 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
 
 our @EXPORT = qw( CheckDigits );
 
-use version; our $VERSION = qv('1.2.0');
+use version; our $VERSION = qv('1.3.0');
 
 my %methods = (
-    'mbase-001'          => 'Algorithm::CheckDigits::MBase_001',
-    'upc'                => 'Algorithm::CheckDigits::MBase_001',
-    'mbase-002'          => 'Algorithm::CheckDigits::MBase_002',
-    'blutbeutel'         => 'Algorithm::CheckDigits::MBase_002',
-    'bzue_de'            => 'Algorithm::CheckDigits::MBase_002',
-    'ustid_de'           => 'Algorithm::CheckDigits::MBase_002',
-    'vatrn_de'           => 'Algorithm::CheckDigits::MBase_002',
-    'mbase-003'          => 'Algorithm::CheckDigits::MBase_003',
-    'sici'               => 'Algorithm::CheckDigits::MBase_003',
-    'm07-001'            => 'Algorithm::CheckDigits::M07_001',
-    'm09-001'            => 'Algorithm::CheckDigits::M09_001',
-    'euronote'           => 'Algorithm::CheckDigits::M09_001',
-    'm10-001'            => 'Algorithm::CheckDigits::M10_001',
-    'amex'               => 'Algorithm::CheckDigits::M10_001',
-    'bahncard'           => 'Algorithm::CheckDigits::M10_001',
-    'cusip'              => 'Algorithm::CheckDigits::M10_001',
-    'diners'             => 'Algorithm::CheckDigits::M10_001',
-    'discover'           => 'Algorithm::CheckDigits::M10_001',
-    'enroute'            => 'Algorithm::CheckDigits::M10_001',
-    'eurocard'           => 'Algorithm::CheckDigits::M10_001',
-    'happydigits'        => 'Algorithm::CheckDigits::M10_001',
-    'jcb'                => 'Algorithm::CheckDigits::M10_001',
-    'klubkarstadt'       => 'Algorithm::CheckDigits::M10_001',
-    'mastercard'         => 'Algorithm::CheckDigits::M10_001',
-    'miles&more'         => 'Algorithm::CheckDigits::M10_001',
-    'visa'               => 'Algorithm::CheckDigits::M10_001',
-    'isin'               => 'Algorithm::CheckDigits::M10_001',
-    'imei'               => 'Algorithm::CheckDigits::M10_001',
-    'imeisv'             => 'Algorithm::CheckDigits::M10_001',
-    'm10-002'            => 'Algorithm::CheckDigits::M10_002',
-    'siren'              => 'Algorithm::CheckDigits::M10_002',
-    'siret'              => 'Algorithm::CheckDigits::M10_002',
-    'm10-003'            => 'Algorithm::CheckDigits::M10_003',
-    'ismn'               => 'Algorithm::CheckDigits::M10_003',
-    'm10-004'            => 'Algorithm::CheckDigits::M10_004',
-    'ean'                => 'Algorithm::CheckDigits::M10_004',
-    'iln'                => 'Algorithm::CheckDigits::M10_004',
-    'nve'                => 'Algorithm::CheckDigits::M10_004',
-    '2aus5'              => 'Algorithm::CheckDigits::M10_004',
-    'isbn13'             => 'Algorithm::CheckDigits::M10_004',
-    'm10-005'            => 'Algorithm::CheckDigits::M10_005',
-    'identcode_dp'       => 'Algorithm::CheckDigits::M10_005',
-    'leitcode_dp'        => 'Algorithm::CheckDigits::M10_005',
-    'm10-006'            => 'Algorithm::CheckDigits::M10_006',
-    'rentenversicherung' => 'Algorithm::CheckDigits::M10_006',
-    'm10-008'            => 'Algorithm::CheckDigits::M10_008',
-    'sedol'              => 'Algorithm::CheckDigits::M10_008',
-    'm10-009'            => 'Algorithm::CheckDigits::M10_009',
-    'betriebsnummer'     => 'Algorithm::CheckDigits::M10_009',
-    'm10-010'            => 'Algorithm::CheckDigits::M10_010',
-    'postcheckkonti'     => 'Algorithm::CheckDigits::M10_010',
-    'm10-011'            => 'Algorithm::CheckDigits::M10_011',
-    'ups'                => 'Algorithm::CheckDigits::M10_011',
-    'm11-001'            => 'Algorithm::CheckDigits::M11_001',
-    'isbn'               => 'Algorithm::CheckDigits::M11_001',
-    'issn'               => 'Algorithm::CheckDigits::M11_001',
-    'ustid_pt'           => 'Algorithm::CheckDigits::M11_001',
-    'vatrn_pt'           => 'Algorithm::CheckDigits::M11_001',
-    'hkid'               => 'Algorithm::CheckDigits::M11_001',
-    'wagonnr_br'         => 'Algorithm::CheckDigits::M11_001',
-    'nhs_gb'             => 'Algorithm::CheckDigits::M11_001',
-    'vat_sl'             => 'Algorithm::CheckDigits::M11_001',
-    'm11-002'            => 'Algorithm::CheckDigits::M11_002',
-    'pzn'                => 'Algorithm::CheckDigits::M11_002',
-    'm11-003'            => 'Algorithm::CheckDigits::M11_003',
-    'pkz'                => 'Algorithm::CheckDigits::M11_003',
-    'm11-004'            => 'Algorithm::CheckDigits::M11_004',
-    'cpf'                => 'Algorithm::CheckDigits::M11_004',
-    'titulo_eleitor'     => 'Algorithm::CheckDigits::M11_004',
-    'm11-006'            => 'Algorithm::CheckDigits::M11_006',
-    'ccc_es'             => 'Algorithm::CheckDigits::M11_006',
-    'm11-007'            => 'Algorithm::CheckDigits::M11_007',
-    'ustid_fi'           => 'Algorithm::CheckDigits::M11_007',
-    'vatrn_fi'           => 'Algorithm::CheckDigits::M11_007',
-    'm11-008'            => 'Algorithm::CheckDigits::M11_008',
-    'ustid_dk'           => 'Algorithm::CheckDigits::M11_008',
-    'vatrn_dk'           => 'Algorithm::CheckDigits::M11_008',
-    'm11-009'            => 'Algorithm::CheckDigits::M11_009',
-    'nric_sg'            => 'Algorithm::CheckDigits::M11_009',
-    'm11-010'            => 'Algorithm::CheckDigits::M11_010',
-    'ahv_ch'             => 'Algorithm::CheckDigits::M11_010',
-    'm11-011'            => 'Algorithm::CheckDigits::M11_011',
-    'ustid_nl'           => 'Algorithm::CheckDigits::M11_011',
-    'vatrn_nl'           => 'Algorithm::CheckDigits::M11_011',
-    'm11-012'            => 'Algorithm::CheckDigits::M11_012',
-    'bwpk_de'            => 'Algorithm::CheckDigits::M11_012',
-    'm11-013'            => 'Algorithm::CheckDigits::M11_013',
-    'ustid_gr'           => 'Algorithm::CheckDigits::M11_013',
-    'vatrn_gr'           => 'Algorithm::CheckDigits::M11_013',
-    'm11-015'            => 'Algorithm::CheckDigits::M11_015',
-    'esr5_ch'            => 'Algorithm::CheckDigits::M11_015',
-    'm11-016'            => 'Algorithm::CheckDigits::M11_016',
-    'ustid_pl'           => 'Algorithm::CheckDigits::M11_016',
-    'vatrn_pl'           => 'Algorithm::CheckDigits::M11_016',
-    'nip'                => 'Algorithm::CheckDigits::M11_016',
-    'm11-017'            => 'Algorithm::CheckDigits::M11_017',
-    'ecno'               => 'Algorithm::CheckDigits::M11_017',
-    'ec-no'              => 'Algorithm::CheckDigits::M11_017',
-    'einecs'             => 'Algorithm::CheckDigits::M11_017',
-    'elincs'             => 'Algorithm::CheckDigits::M11_017',
-    'm16-001'            => 'Algorithm::CheckDigits::M16_001',
-    'isan'               => 'Algorithm::CheckDigits::M16_001',
-    'm23-001'            => 'Algorithm::CheckDigits::M23_001',
-    'dni_es'             => 'Algorithm::CheckDigits::M23_001',
-    'm23-002'            => 'Algorithm::CheckDigits::M23_002',
-    'ustid_ie'           => 'Algorithm::CheckDigits::M23_002',
-    'vatrn_ie'           => 'Algorithm::CheckDigits::M23_002',
-    'm43-001'            => 'Algorithm::CheckDigits::M43_001',
-    'code_39'            => 'Algorithm::CheckDigits::M43_001',
-    'm89-001'            => 'Algorithm::CheckDigits::M89_001',
-    'ustid_lu'           => 'Algorithm::CheckDigits::M89_001',
-    'vatrn_lu'           => 'Algorithm::CheckDigits::M89_001',
-    'm97-001'            => 'Algorithm::CheckDigits::M97_001',
-    'ustid_be'           => 'Algorithm::CheckDigits::M97_001',
-    'vatrn_be'           => 'Algorithm::CheckDigits::M97_001',
-    'm97-002'            => 'Algorithm::CheckDigits::M97_002',
-    'iban'               => 'Algorithm::CheckDigits::M97_002',
-    'mxx-001'            => 'Algorithm::CheckDigits::MXX_001',
-    'pa_de'              => 'Algorithm::CheckDigits::MXX_001',
-    'aba_rn'             => 'Algorithm::CheckDigits::MXX_001',
-    'mxx-002'            => 'Algorithm::CheckDigits::MXX_002',
-    'cas'                => 'Algorithm::CheckDigits::MXX_002',
-    'mxx-003'            => 'Algorithm::CheckDigits::MXX_003',
-    'dem'                => 'Algorithm::CheckDigits::MXX_003',
-    'mxx-004'            => 'Algorithm::CheckDigits::MXX_004',
-    'ustid_at'           => 'Algorithm::CheckDigits::MXX_004',
-    'vatrn_at'           => 'Algorithm::CheckDigits::MXX_004',
-    'mxx-005'            => 'Algorithm::CheckDigits::MXX_005',
-    'esr9_ch'            => 'Algorithm::CheckDigits::MXX_005',
-    'verhoeff'           => 'Algorithm::CheckDigits::MXX_006',
+    'upc'                => [ 'Algorithm::CheckDigits::MBase_001',
+                              'Universal Product Code, UPC (US, CA)' ],
+    'blutbeutel'         => [ 'Algorithm::CheckDigits::MBase_002',
+                              'Eurocode, blood bags' ],
+    'bzue_de'            => [ 'Algorithm::CheckDigits::MBase_002',
+                              'Beleglose Zahlscheinüberweisung, BZÜ (DE)' ],
+    'ustid_de'           => [ 'Algorithm::CheckDigits::MBase_002',
+                              'Umsatzsteuer-Identifikationsnummer (DE)' ],
+    'sici'               => [ 'Algorithm::CheckDigits::MBase_003',
+                              'Value Added Tax number, VAT (DE)' ],
+    'euronote'           => [ 'Algorithm::CheckDigits::M09_001',
+                              'Euro bank notes, EUR' ],
+    'amex'               => [ 'Algorithm::CheckDigits::M10_001',
+                              'American Express credit cards' ],
+    'bahncard'           => [ 'Algorithm::CheckDigits::M10_001',
+                              'DB Bahncard (DE)' ],
+    'cusip'              => [ 'Algorithm::CheckDigits::M10_001',
+        'Committee on Uniform Security Identification Procedures, CUSIP (US)' ],
+    'diners'             => [ 'Algorithm::CheckDigits::M10_001',
+                              q(Diner's club credit cards) ],
+    'discover'           => [ 'Algorithm::CheckDigits::M10_001',
+                              'Discover credit cards' ],
+    'enroute'            => [ 'Algorithm::CheckDigits::M10_001',
+                              'EnRoute credit cards' ],
+    'eurocard'           => [ 'Algorithm::CheckDigits::M10_001',
+                              'Eurocard credit cards' ],
+    'happydigits'        => [ 'Algorithm::CheckDigits::M10_001',
+                              'Happy Digits (DE)' ],
+    'jcb'                => [ 'Algorithm::CheckDigits::M10_001',
+                              'JCB credit cards' ],
+    'klubkarstadt'       => [ 'Algorithm::CheckDigits::M10_001',
+                              'Klub Karstadt (DE)' ],
+    'mastercard'         => [ 'Algorithm::CheckDigits::M10_001',
+                              'Mastercard credit cards' ],
+    'miles&more'         => [ 'Algorithm::CheckDigits::M10_001',
+                              'Miles & More, Lufthansa (DE)' ],
+    'visa'               => [ 'Algorithm::CheckDigits::M10_001',
+                              'VISA credit cards' ],
+    'isin'               => [ 'Algorithm::CheckDigits::M10_001',
+                       'International Securities Identifikation Number, ISIN' ],
+    'imei'               => [ 'Algorithm::CheckDigits::M10_001',
+                      'International Mobile Station Equipment Identity, IMEI' ],
+    'imeisv'             => [ 'Algorithm::CheckDigits::M10_001',
+'International Mobile Station Equipment Identity and Software Version Number' ],
+    'siren'              => [ 'Algorithm::CheckDigits::M10_002',
+                              'SIREN (FR)' ],
+    'siret'              => [ 'Algorithm::CheckDigits::M10_002',
+                              'SIRET (FR)' ],
+    'ismn'               => [ 'Algorithm::CheckDigits::M10_003',
+                              'International Standard Music Number, ISMN' ],
+    'ean'                => [ 'Algorithm::CheckDigits::M10_004',
+                              'European Article Number, EAN' ],
+    'iln'                => [ 'Algorithm::CheckDigits::M10_004',
+                              'Global Location Number, GLN' ],
+    'nve'                => [ 'Algorithm::CheckDigits::M10_004',
+                              'Nummer der Versandeinheit, NVE, SSCC' ],
+    '2aus5'              => [ 'Algorithm::CheckDigits::M10_004',
+                              '2 aus 5, 2 of 5, 2/5' ],
+    'isbn13'             => [ 'Algorithm::CheckDigits::M10_004',
+                              'International Standard Book Number, ISBN13' ],
+    'identcode_dp'       => [ 'Algorithm::CheckDigits::M10_005',
+                              'Identcode Deutsche Post AG (DE)' ],
+    'leitcode_dp'        => [ 'Algorithm::CheckDigits::M10_005',
+                              'Leitcode Deutsche Post AG (DE)' ],
+    'rentenversicherung' => [ 'Algorithm::CheckDigits::M10_006',
+                              'Rentenversicherungsnummer, VSNR (DE)' ],
+    'sedol'              => [ 'Algorithm::CheckDigits::M10_008',
+                          'Stock Exchange Daily Official List, SEDOL (GB)' ],
+    'betriebsnummer'     => [ 'Algorithm::CheckDigits::M10_009',
+                              'Betriebsnummer (DE)' ],
+    'postcheckkonti'     => [ 'Algorithm::CheckDigits::M10_010',
+                              'Postscheckkonti (CH)' ],
+    'ups'                => [ 'Algorithm::CheckDigits::M10_011',
+                              'United Parcel Service, UPS' ],
+    'isbn'               => [ 'Algorithm::CheckDigits::M11_001',
+                              'International Standard Book Number, ISBN10' ],
+    'issn'               => [ 'Algorithm::CheckDigits::M11_001',
+                              'International Standard Serial Number, ISSN' ],
+    'ustid_pt'           => [ 'Algorithm::CheckDigits::M11_001',
+                              'Umsatzsteuer-Identifikationsnummer (PT)' ],
+    'vatrn_pt'           => [ 'Algorithm::CheckDigits::M11_001',
+                              'Value Added Tax number, VAT (PT)' ],
+    'hkid'               => [ 'Algorithm::CheckDigits::M11_001',
+                              'Hong Kong Identity Card, HKID (HK)' ],
+    'wagonnr_br'         => [ 'Algorithm::CheckDigits::M11_001',
+                              'Codificação dos vagões (BR)' ],
+    'nhs_gb'             => [ 'Algorithm::CheckDigits::M11_001',
+                              'National Health Service, NHS (GB)' ],
+    'vat_sl'             => [ 'Algorithm::CheckDigits::M11_001',
+                              'Value Added Tax number, VAT (SL)' ],
+    'pzn'                => [ 'Algorithm::CheckDigits::M11_002',
+                              'Pharmazentralnummer (DE)' ],
+    'pkz'                => [ 'Algorithm::CheckDigits::M11_003',
+                              'Personenkennzahl der DDR' ],
+    'cpf'                => [ 'Algorithm::CheckDigits::M11_004',
+                              'Cadastro de Pessoas Físicas, CPF (BR)' ],
+    'titulo_eleitor'     => [ 'Algorithm::CheckDigits::M11_004',
+                              'Título Eleitoral (BR)' ],
+    'ccc_es'             => [ 'Algorithm::CheckDigits::M11_006',
+                              'Código de Cuenta Corriente, CCC (ES)' ],
+    'ustid_fi'           => [ 'Algorithm::CheckDigits::M11_007',
+                              'Umsatzsteuer-Identifikationsnummer (FI)' ],
+    'vatrn_fi'           => [ 'Algorithm::CheckDigits::M11_007',
+                              'Value Added Tax number, VAT (FI)' ],
+    'ustid_dk'           => [ 'Algorithm::CheckDigits::M11_008',
+                              'Umsatzsteuer-Identifikationsnummer (DK)' ],
+    'vatrn_dk'           => [ 'Algorithm::CheckDigits::M11_008',
+                              'Value Added Tax number, VAT (DK)' ],
+    'nric_sg'            => [ 'Algorithm::CheckDigits::M11_009',
+                       'National Registration Identity Card, NRIC (SG)' ],
+    'ahv_ch'             => [ 'Algorithm::CheckDigits::M11_010',
+              'Alters- und Hinterlassenenversicherungsnummer, AHV (CH)' ],
+    'ustid_nl'           => [ 'Algorithm::CheckDigits::M11_011',
+                              'Umsatzsteuer-Identifikationsnummer (NL)' ],
+    'vatrn_nl'           => [ 'Algorithm::CheckDigits::M11_011',
+                              'Value Added Tax number, VAT (NL)' ],
+    'bwpk_de'            => [ 'Algorithm::CheckDigits::M11_012',
+                              'Personenkennummer der Bundeswehr (DE)' ],
+    'ustid_gr'           => [ 'Algorithm::CheckDigits::M11_013',
+                              'Umsatzsteuer-Identifikationsnummer (GR)' ],
+    'vatrn_gr'           => [ 'Algorithm::CheckDigits::M11_013',
+                              'Value Added Tax number, VAT (GR)' ],
+    'esr5_ch'            => [ 'Algorithm::CheckDigits::M11_015',
+                              'Einzahlungsschein mit Referenz, ESR5 (CH)' ],
+    'ustid_pl'           => [ 'Algorithm::CheckDigits::M11_016',
+                              'Umsatzsteuer-Identifikationsnummer (PL)' ],
+    'vatrn_pl'           => [ 'Algorithm::CheckDigits::M11_016',
+                              'Value Added Tax number, VAT (PL)' ],
+    'nip'                => [ 'Algorithm::CheckDigits::M11_016',
+                              'numer identyfikacji podatkowej, NIP' ],
+    'ecno'               => [ 'Algorithm::CheckDigits::M11_017',
+                    'European Commission number, EC-No (for chemicals)' ],
+    'einecs'             => [ 'Algorithm::CheckDigits::M11_017',
+'European Inventory of Existing Commercial Chemical Substances, EINECS' ],
+    'elincs'             => [ 'Algorithm::CheckDigits::M11_017',
+                'European List of Notified Chemical Substances, ELINCS' ],
+    'isan'               => [ 'Algorithm::CheckDigits::M16_001',
+                      'International Standard Audiovisual Number, ISAN' ],
+    'dni_es'             => [ 'Algorithm::CheckDigits::M23_001',
+                              'Documento nacional de identidad (ES)' ],
+    'ustid_ie'           => [ 'Algorithm::CheckDigits::M23_002',
+                              'Umsatzsteuer-Identifikationsnummer (IE)' ],
+    'vatrn_ie'           => [ 'Algorithm::CheckDigits::M23_002',
+                              'Value Added Tax number, VAT (IE)' ],
+    'code_39'            => [ 'Algorithm::CheckDigits::M43_001',
+                              'Code39, 3 of 9' ],
+    'ustid_lu'           => [ 'Algorithm::CheckDigits::M89_001',
+                              'Umsatzsteuer-Identifikationsnummer (LU)' ],
+    'vatrn_lu'           => [ 'Algorithm::CheckDigits::M89_001',
+                              'Value Added Tax number, VAT (LU)' ],
+    'ustid_be'           => [ 'Algorithm::CheckDigits::M97_001',
+                              'Umsatzsteuer-Identifikationsnummer (BE)' ],
+    'vatrn_be'           => [ 'Algorithm::CheckDigits::M97_001',
+                              'Value Added Tax number, VAT (BE)' ],
+    'iban'               => [ 'Algorithm::CheckDigits::M97_002',
+                              'International Bank Account Number (IBAN)' ],
+    'pa_de'              => [ 'Algorithm::CheckDigits::MXX_001',
+                              'Personalausweis (DE)' ],
+    'aba_rn'             => [ 'Algorithm::CheckDigits::MXX_001',
+                     'American Bankers Association routing number (ABA RN)' ],
+    'cas'                => [ 'Algorithm::CheckDigits::MXX_002',
+                              'Chemical abstract service, CAS' ],
+    'dem'                => [ 'Algorithm::CheckDigits::MXX_003',
+                              'Deutsche Mark Banknoten, DEM' ],
+    'ustid_at'           => [ 'Algorithm::CheckDigits::MXX_004',
+                              'Umsatzsteuer-Identifikationsnummer (AT)' ],
+    'vatrn_at'           => [ 'Algorithm::CheckDigits::MXX_004',
+                              'Value Added Tax number, VAT (AT)' ],
+    'esr9_ch'            => [ 'Algorithm::CheckDigits::MXX_005',
+                              'Einzahlungsschein mit Referenz, ESR9 (CH)' ],
+    'verhoeff'           => [ 'Algorithm::CheckDigits::MXX_006',
+                              'Verhoeff scheme' ],
 );
 
 sub CheckDigits {
     my $method = shift || '';
 
     if ( my $pkg = $methods{ lc($method) } ) {
-        my $file = $pkg;
+        my $module = $pkg->[0];
+        my $file   = $pkg->[0];
         $file =~ s{::}{/}g;
         require "$file.pm";
-        return new $pkg($method);
+        return new $module($method);
     }
     else {
         die "Don't know checkdigit algorithm for '$method'!";
@@ -185,6 +228,38 @@ sub method_list {
     return wantarray ? @methods : \@methods;
 }    # method_list()
 
+sub method_descriptions {
+    my @meths = @_;
+    if ($meths[0] eq 'Algorithm::CheckDigits') {
+        # it was called Algorithm::CheckDigits->method_descriptions
+        shift @meths;
+    }
+    if (0 == scalar @meths) {
+        @meths = keys %methods;
+    }
+    my %descr = map { $_ => ($methods{$_}) ? $methods{$_}->[1]
+                         :                   'unknown'         } @meths;
+    return wantarray ? %descr : \%descr;
+} # method_descriptions()
+
+sub plug_in {
+    if ('Algorithm::CheckDigits' eq $_[0]) {
+        shift;
+    }
+    my $module = shift ||
+       die "you need to specify a module except 'Algorithm::CheckDigits'";
+    my $descr  = shift || "algorithm of module $module";
+    my $key    = lc shift || 'plalg';
+    if (exists $methods{$key}) {
+        $key .= ',1';
+    }
+    while (exists $methods{$key}) {
+        $key =~ s/(\d+)$/my $y = $1; ++$y/e;
+    }
+    $methods{$key} = [ $module, $descr ];
+    return $key;
+} # plug_in()
+
 sub print_methods {
     foreach my $method ( sort keys %methods ) {
         print "$method => $methods{$method}\n";
@@ -221,6 +296,7 @@ or
   use Algorithm::CheckDigits;
   
   @ml = Algorithm::CheckDigits->method_list();
+  %md = Algorithm::CheckDigits->method_descriptions();
 
   $isbn = CheckDigits('ISBN');
 
@@ -275,10 +351,33 @@ digit.
 
 =back
 
+=head2 Algorithm::CheckDigits::plug_in($module, $description, $prefkey)
+
+Register a module that provides the same four methods as above. This function
+returns a handle with which the registered module can be instantiated.
+
+The first argument C<$module> is the module to be used for this plugin. This
+argument is mandatory. Do not register 'Algorithm::CheckDigits'.
+
+The second argument is a short description of the algorithm. If it is omitted,
+the string C<algorithm of module $module> will be taken.
+
+The third argument is the preferred key for this algorithm. The C<plug_in()>
+function does not guarantee to register the algorithm with this key. Instead
+it returns the key under which the algorithm is registered.
+
+See L</"REGISTERING PLUGINS"> for more information on registering plugins.
+
 =head2 Algorithm::CheckDigits::method_list()
 
 Returns a list of known methods for check digit computation.
 
+=head2 Algorithm::CheckDigits::method_descriptions()
+
+Returns a hash of descriptions for the known methods for check digit
+computations. The keys of the hash are the values returned by
+C<method_list()>.
+
 =head2 Algorithm::CheckDigits::print_methods()
 
 Returns a list of known methods for check digit computation.
@@ -296,177 +395,172 @@ At the moment these methods to compute check digits are provided:
 
 =over 4
 
-=item m07-001
-
-See L<Algorithm::CheckDigits::M07_001>.
-
-=item euronote, m09-001
+=item euronote
 
 European bank notes, see L<Algorithm::CheckDigits::M09_001>.
 
 =item amex, bahncard, diners, discover, enroute, eurocard, happydigits,
-      isin, jcb, klubkarstadt, mastercard, miles&more, visa, m09-001,
-      imei, imeisv
+      isin, jcb, klubkarstadt, mastercard, miles&more, visa, imei, imeisv
 
 See L<Algorithm::CheckDigits::M10_001>.
 
-=item siren, siret, m10-002
+=item siren, siret
 
 See L<Algorithm::CheckDigits::M10_002>.
 
-=item ismn, m10-003
+=item ismn
 
 See L<Algorithm::CheckDigits::M10_003>.
 
-=item ean, iln, isbn13, nve, 2aus5, m10-004
+=item ean, iln, isbn13, nve, 2aus5
 
 See L<Algorithm::CheckDigits::M10_004>.
 
-=item identcode_dp, leitcode_dp, m10-005
+=item identcode_dp, leitcode_dp
 
 See L<Algorithm::CheckDigits::M10_005>.
 
-=item rentenversicherung, m10-006
+=item rentenversicherung
 
 See L<Algorithm::CheckDigits::M10_006>.
 
-=item sedol, m10-008
+=item sedol
 
 See L<Algorithm::CheckDigits::M10_008>.
 
-=item betriebsnummer, m10-009
+=item betriebsnummer
 
 See L<Algorithm::CheckDigits::M10_009>.
 
-=item postscheckkonti, m10-010
+=item postscheckkonti
 
 See L<Algorithm::CheckDigits::M10_010>.
 
-=item ups, m10-011
+=item ups
 
 See L<Algorithm::CheckDigits::M10_011>.
 
-=item hkid, isbn, issn, nhs_gb, ustid_pt, vat_sl, wagonnr_br, m11-001
+=item hkid, isbn, issn, nhs_gb, ustid_pt, vat_sl, wagonnr_br
 
 See L<Algorithm::CheckDigits::M11_001>.
 
-=item pzn, m11-002
+=item pzn
 
 See L<Algorithm::CheckDigits::M11_002>.
 
-=item pkz, m11-003
+=item pkz
 
 See L<Algorithm::CheckDigits::M11_003>.
 
-=item cpf, titulo_eleitor, m11-004
+=item cpf, titulo_eleitor
 
 See L<Algorithm::CheckDigits::M11_004>.
 
-=item ccc_es, m11-006
+=item ccc_es
 
 See L<Algorithm::CheckDigits::M11_006>.
 
-=item ustid_fi, vatrn_fi, m11-007
+=item ustid_fi, vatrn_fi
 
 See L<Algorithm::CheckDigits::M11_007>.
 
-=item ustid_dk, vatrn_dk, m11-008
+=item ustid_dk, vatrn_dk
 
 See L<Algorithm::CheckDigits::M11_008>.
 
-=item nric_sg, m11-009
+=item nric_sg
 
 See L<Algorithm::CheckDigits::M11_009>.
 
-=item ahv_ch, m11-010
+=item ahv_ch
 
 See L<Algorithm::CheckDigits::M11_010>.
 
-=item ustid_nl, vatrn_nl, m11-011
+=item ustid_nl, vatrn_nl
 
 See L<Algorithm::CheckDigits::M11_011>.
 
-=item bwpk_de, m11-012
+=item bwpk_de
 
 See L<Algorithm::CheckDigits::M11_012>.
 
-=item ustid_gr, vatrn_gr, m11-013
+=item ustid_gr, vatrn_gr
 
 See L<Algorithm::CheckDigits::M11_013>.
 
-=item esr5_ch, m11-015
+=item esr5_ch
 
 See L<Algorithm::CheckDigits::M11_015>.
 
-=item ustid_pl, vatrn_pl, m11-016
+=item ustid_pl, vatrn_pl
 
 See L<Algorithm::CheckDigits::M11_016>.
 
-=item ecno, ec-no, einecs, elincs, m11-017
+=item ecno, ec-no, einecs, elincs
 
 See L<Algorithm::CheckDigits::M11_017>.
 
-=item isan, m16-001
+=item isan
 
 See L<Algorithm::CheckDigits::M16_001>.
 
-=item dni_es, m23-001
+=item dni_es
 
 See L<Algorithm::CheckDigits::M23_001>.
 
-=item ustid_ie, vatrn_ie, m23-002
+=item ustid_ie, vatrn_ie
 
 See L<Algorithm::CheckDigits::M23_002>.
 
-=item code_39, m43-001
+=item code_39
 
 See L<Algorithm::CheckDigits::M43_001>.
 
-=item ustid_lu, vatrn_lu, m89-001
+=item ustid_lu, vatrn_lu
 
 See L<Algorithm::CheckDigits::M89_001>.
 
-=item ustid_be, vatrn_be, m97-001
+=item ustid_be, vatrn_be
 
 See L<Algorithm::CheckDigits::M97_001>.
 
-=item iban, m97-002
+=item iban
 
 See L<Algorithm::CheckDigits::M97_002>.
 
-=item upc, mbase-001
+=item upc
 
 See L<Algorithm::CheckDigits::MBase_001>.
 
-=item blutbeutel, bzue_de, ustid_de, vatrn_de, mbase-002
+=item blutbeutel, bzue_de, ustid_de, vatrn_de
 
 See L<Algorithm::CheckDigits::MBase_002>.
 
-=item sici, mbase-003
+=item sici
 
 See L<Algorithm::CheckDigits::MBase_003>.
 
-=item pa_de, mxx-001
+=item pa_de
 
 See L<Algorithm::CheckDigits::MXX_001>.
 
-=item cas, mxx-002
+=item cas
 
 See L<Algorithm::CheckDigits::MXX_002>.
 
-=item dem, mxx-003
+=item dem
 
 Old german bank notes (DEM), see L<Algorithm::CheckDigits::MXX_003>.
 
-=item ustid_at, vatrn_at, mxx-004
+=item ustid_at, vatrn_at
 
 See L<Algorithm::CheckDigits::MXX_004>.
 
-=item esr9_ch, mxx-005
+=item esr9_ch
 
 See L<Algorithm::CheckDigits::MXX_005>.
 
-=item verhoeff, mxx-006
+=item verhoeff
 
 Verhoeff scheme, see L<Algorithm::CheckDigits::MXX_006> or
 L<Algorithm::Verhoeff>
@@ -475,7 +569,76 @@ L<Algorithm::Verhoeff>
 
 =head2 EXPORT
 
-None by default.
+This module exports the Function C<CheckDigits()> that is used to create an
+instance of a checker with the given algorithm.
+
+=head1 REGISTERING PLUGINS
+
+Brian T. Wightman was the first, asking me to add a plugin registry to
+Algorithm::CheckDigits and so I added the function C<plug_in()> that does just
+this, registering plug in modules to be used just like the modules in the
+distribution of this module.
+
+Providing some means to add additional algorithms without the need to change
+the module has the benefit that the user of those additional algorithms may
+easily use them with the same interface as the other algorithms without having
+to wait for a new version, that may or may not include the wanted algorithm.
+
+But there is a problem: the user must be able to select the new algorithms
+like he did with the other ones. And the catch is: since these new algorithms
+are developed independently there is no guarantee that no more than one
+module applies for the same handle. I could have implemented some simple
+strategies like last one wins (the module that registers last for a given
+handle is the one that is choosen) or first one wins (the first registered
+module is choosen). Instead I went for something more complex to assure that
+every module that wants to get registered will be registered and that every
+registered module will be accessible by the same handle as long as the program
+runs. To make this work C<plug_in()> sees the third argument only as a hint
+how the handle should look like, when a module is registered. It returns the
+real handle with which the algorithm can be instantiated. That means a
+developer of a plugin module cannot make the handle immediately available like
+I did for the modules in the distribution. Instead there should be something
+like a public variable or function that returns the handle as it came back
+from the C<plug_in()> function.
+
+This could go like this in the module:
+
+ package Algorithm::XyZ;
+
+ use Algorithm::CheckDigits;
+
+ our $xyz = Algorithm::CheckDigits::plug_in('Algorithm::XyZ',
+                                            'XyZ check digits',
+                                            'xyz');
+
+And the user of this algorithm would write something like this:
+
+ use Algorithm::CheckDigits;
+ use Algorithm::XyZ;
+
+ my $cd = CheckDigits($Algorithm::XyZ::xyz);
+
+ if ($cd->is_valid($some_number)) {
+     # do something
+ }
+
+Please have a look at the plugin tests in the test directory (I<t/plugin*.t>)
+and the accompanying modules (I<t/PluginLib*.pm>) for example usage. You may
+also try to load an additional module with the scripts in I<bin> and
+I<cgi-bin> and look for the additional algorithms in the output:
+
+ perl -Ilib -It -MPluginLibA bin/checkdigits.pl list
+
+ perl -Ilib -It -MPluginLibA cgi-bin/checkdigits.cgi
+
+=head2 Namespace
+
+I would like to ask you to use any namespace below or outside but not direct
+Algorithm::CheckDigits. That means for instance for the XyZ algorithm,
+Algorithm::XyZ would be fine, Algorithm::CheckDigits::Plugin::XyZ or
+Algorithm::CheckDigits::X::XyZ would be fine too. But
+Algorithm::CheckDigits::XyZ could collide with some future version of the
+Algorithm::CheckDigits distribution, so please avoid this namespace.
 
 =head1 SEE ALSO
 
@@ -484,6 +647,9 @@ F<www.pruefziffernberechnung.de>.
 
 =head1 BUGS AND LIMITATIONS
 
+The function C<plug_in()> dies if you try to register the module
+'Algorithm::CheckDigits'.
+
 Please report any bugs or feature requests to
 C<bug-algorithm-checkdigits@rt.cpan.org>, or through the web interface at
 L<http://rt.cpan.org>.
@@ -497,9 +663,11 @@ Mathias Weidner, C<< mamawe@cpan.org >>
 Petri Oksanen made me aware that CheckDigits('IMEI') would invoke no test at
 all since there was no entry for this in the methods hash.
 
+Brian T. Wightman made me think about and implement the plugin interface.
+
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2004-2010 by Mathias Weidner
+Copyright 2004-2013 by Mathias Weidner
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. See L<perlartistic>.
@@ -0,0 +1,73 @@
+# vim: set ts=4 sw=4 tw=78 si et:
+package PluginLibA;
+
+use strict;
+use warnings;
+
+use Algorithm::CheckDigits;
+
+# This module inherits from Algorithm::CheckDigits end reexports the function
+# CheckDigits() so the user of this module does not need to explicitely
+# 'use Algorithm::CheckDigits;'.
+
+our @EXPORT = qw(CheckDigits);
+our @ISA = qw(Algorithm::CheckDigits);
+
+# These variables store the keys under which the variants of the algorithm in
+# this module are registered with Algorithm::CheckDigits. They must be made
+# publicly accessible for the user of this module.
+
+our $meth1 = Algorithm::CheckDigits::plug_in('PluginLibA', 'returns 1', 'pla');
+our $meth2 = Algorithm::CheckDigits::plug_in('PluginLibA', 'returns 2', 'pla');
+
+# It's possible to use the -> notation to access the plug_in() function.
+
+our $meth3 = Algorithm::CheckDigits->plug_in('PluginLibA', 'returns 3', 'pla');
+
+# Since this module provides variants of the algorithm it stores the key used
+# to create the instance, which is given as the first argument after the class
+# name.
+
+sub new {
+    my $proto = shift;
+    my $type  = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = bless( {}, $class );
+    $self->{type} = lc($type);
+    return $self;
+}    # new()
+
+# This is just one example on how to use the registration keys returned by
+# Algorithm::CheckDigits::plug_in().
+
+my %methods = (
+    $meth1 => 1,
+    $meth2 => 2,
+    $meth3 => 3,
+);
+
+sub is_valid {
+    my ($self,$number) = @_;
+
+    return $methods{$self->{type}} == $number;
+}
+
+sub complete {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+sub basenumber {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+sub checkdigit {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+1;
@@ -0,0 +1,87 @@
+# vim: set ts=4 sw=4 tw=78 si et:
+package PluginLibB;
+
+# This module is usable either as a plugin for Algorithm::CheckDigits or
+# stand-alone. As a plugin one can create instances with the CheckDigits()
+# function from Algorithm::CheckDigits. If that modulue is not available,
+# it is possible to create instances with PluginLibB->new().
+# See pluginlibb.t and pluginlibb-without.t for example usage.
+
+use strict;
+use warnings;
+
+# These variables store the keys under which the variants of the algorithm in
+# this module will be registered with Algorithm::CheckDigits if that module is
+# available. They must be made publicly accessible for the user of this module.
+#
+# If there are no variations of the algorithm, it is not necessary to use such
+# variables in stand-alone mode. But for usage together with
+# Algorithm::CheckDigits at least one method per variant is mandatory.
+
+our ($meth1,$meth2,$meth3);
+
+# Since this module should work regardless of the availability of
+# Algorithm::CheckDigits we have to 'eval "use Algorithm::CheckDigits";'.
+
+eval "use Algorithm::CheckDigits";
+if ($@) {
+    $meth1 = 'plb1';
+    $meth2 = 'plb2';
+    $meth3 = 'plb3';
+}
+else {
+    $meth1 = Algorithm::CheckDigits::plug_in('PluginLibB', 'returns 1', 'plb1');
+    $meth2 = Algorithm::CheckDigits::plug_in('PluginLibB', 'returns 2', 'plb2');
+
+    # It's possible to use the -> notation to access the plug_in() function.
+
+    $meth3 = Algorithm::CheckDigits->plug_in('PluginLibB', 'returns 3', 'plb3');
+}
+
+# Since this module provides variants of the algorithm it stores the key used
+# to create the instance, which is given as the first argument after the class
+# name.
+
+sub new {
+    my $proto = shift;
+    my $type  = shift;
+    my $class = ref($proto) || $proto;
+    my $self  = bless( {}, $class );
+    $self->{type} = lc($type);
+    return $self;
+}    # new()
+
+# This is just one example on how to use the registration keys returned by
+# Algorithm::CheckDigits::plug_in().
+
+my %methods = (
+    $meth1 => 1,
+    $meth2 => 2,
+    $meth3 => 3,
+);
+
+sub is_valid {
+    my ($self,$number) = @_;
+
+    return $methods{$self->{type}} == $number;
+}
+
+sub complete {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+sub basenumber {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+sub checkdigit {
+    my ($self) = @_;
+
+    return $methods{$self->{type}};
+}
+
+1;
@@ -0,0 +1,22 @@
+use Test::More;
+
+use lib qw( t );
+
+# Since the module PluginLibA reexports the function CheckDigits() from
+# Algorithm::CheckDigits, we do not need to explicitly use that module to get
+# the function into our name space.
+
+use PluginLibA;
+
+# To get access to the algorithm provided by module PluginLibA, we have to use
+# the keys stored in these publicly accessible variables.
+
+my $cd1 = CheckDigits($PluginLibA::meth1);
+my $cd2 = CheckDigits($PluginLibA::meth2);
+my $cd3 = CheckDigits($PluginLibA::meth3);
+
+is($cd1->checkdigit(234), 1, 'checked method1 of PluginLibA');
+is($cd2->basenumber(234), 2, 'checked method2 of PluginLibA');
+is($cd3->complete(234),   3, 'checked method3 of PluginLibA');
+
+done_testing();
@@ -0,0 +1,18 @@
+use Test::More;
+
+use lib qw( t );
+
+use PluginLibB;
+
+# To get access to the algorithm provided by module PluginLibB, we have to use
+# the keys stored in these publicly accessible variables.
+
+my $cd1 = PluginLibB->new($PluginLibB::meth1);
+my $cd2 = PluginLibB->new($PluginLibB::meth2);
+my $cd3 = PluginLibB->new($PluginLibB::meth3);
+
+is($cd1->checkdigit(234), 1, 'checked method1 of PluginLibB');
+is($cd2->basenumber(234), 2, 'checked method2 of PluginLibB');
+is($cd3->complete(234),   3, 'checked method3 of PluginLibB');
+
+done_testing();
@@ -0,0 +1,23 @@
+use Test::More;
+
+use lib qw( t );
+
+# Since PluginLibB does not inherit from Algorithm::CheckDigits we have to use
+# Algorithm::CheckDigits here to make use of the function CheckDigits() to get
+# our algorithm checker.
+#
+use Algorithm::CheckDigits;
+use PluginLibB;
+
+# To get access to the algorithm provided by module PluginLibB, we have to use
+# the keys stored in these publicly accessible variables.
+
+my $cd1 = CheckDigits($PluginLibB::meth1);
+my $cd2 = CheckDigits($PluginLibB::meth2);
+my $cd3 = CheckDigits($PluginLibB::meth3);
+
+is($cd1->checkdigit(234), 1, 'checked method1 of PluginLibB');
+is($cd2->basenumber(234), 2, 'checked method2 of PluginLibB');
+is($cd3->complete(234),   3, 'checked method3 of PluginLibB');
+
+done_testing();
@@ -27,6 +27,8 @@ use vars qw(@testcases);
 	                '0724-8870' ],
 	[ 'ustid_pt',   '136695973',     '13669597',	 '3',
 	                '136695970' ],
+	[ 'vatrn_pt',   '136695973',     '13669597',	 '3',
+	                '136695970' ],
 	[ 'hkid',       'K1234560',	 'K123456',      '0',
 	                'K1234567' ],
 	[ 'wagonnr_br', '123456-1',	 '123456-',      '1',
@@ -62,11 +64,12 @@ use vars qw(@testcases);
 		  '0724-8679(20040308)6:<138>2.0.TX;2-A',
 	],
 
+	# I don't know what for this method is.
 	# M07-001
-	[ 'm07-001', '0', '', '0',
-	             '1' ],
-        [ 'm07-001', '1234567892', '123456789', '2',
-	             '1234567890' ],
+	#[ 'm07-001', '0', '', '0',
+	#             '1' ],
+        #[ 'm07-001', '1234567892', '123456789', '2',
+	#             '1234567890' ],
 
 	# M09-001
 	[ 'euronote', 'X03854465012', 'X0385446501', '2',