=head1 NAME Geo::Postcodes::Tutorial - How to use the Geo::Postcodes::* modules =head1 SYNOPSIS use Geo::Postcodes::U2; my $postcode = '1104'; my $location = Geo::Postcodes::U2::location_of($postcode); =head1 INTRODUCING UTOPIA This tutorial uses the fictious country I (with country code 'U2'), and the rest of this document will refer to the non-existent module C. Any differences with the two existing country modules (C; Denmark and C; Norway) are explained. =head1 INSTALLING UTOPIA The latest version of I if had it existed, that is) can be installed or updated from CPAN with the following commands (, preferably as root. This will automatically install or update the core module I as well. shell> perl -MCPAN -e shell cpan> install Geo::Postcodes::U2 It may be possible to use the command C instead of the first line. =head1 USING UTOPIA Include the following line in the program, after installing the module: use Geo::Postcodes::U2; =head1 VERIFYING UTOPIA =head2 legal Use the I procedure to check that the specified postcode is legal, i.e. that it follows the syntax rules for our utopian postcodes. Utopian postcodes are four digit numbers, and the lowest number in use is '1003'. This procedure is programmed to return true for any four digit number where the first digit is non-zero. $boolean = Geo::Postcodes::U2::legal('ABBA'); # 0 -> Illegal $boolean = Geo::Postcodes::U2::legal('0900'); # 0 -> Illegal $boolean = Geo::Postcodes::U2::legal('1900'); # 1 -> Legal $boolean = Geo::Postcodes::U2::legal('1000'); # 1 -> Legal =head2 valid The procedure I will check if the postcode is valid; that it is in actual use. The code may or may not be legal. $boolean = Geo::Postcodes::U2::valid('1000'); # 0 -> Not in use $boolean = Geo::Postcodes::U2::valid('ABBA'); # 0 -> Not in use =head1 UTOPIAN FIELDS Utopian postcodes support all the 8 fields set up by the core module. Every field is available as C<$P-Exxx> or C, where C is the field name. The procedures/methods will return I if the value is unspecified for the given postcode. =head2 postcode - postcode_of $postcode = $P->postcode(); $postcode = Geo::Postcodes::U2::location_of($postcode); # Silly The actual I value is available with C method, as the object itself does not have this information. The corresponding I-procedure is used internally by L-procedure/method, but should be avoided in applications. =head2 location - location_of $location = $P->location(); $location = Geo::Postcodes::U2::location_of($postcode); The location (or postal location) of the postcode. This is the value shown after the postcode in addresses. =head2 borough - borough_of $borough = $P->borough(); $borough = $Geo::Postcodes::U2::borough_of($postcode); The borough where the postcode is located. This field is not used by danish postcodes. =head2 county - county_of $county = $P->county(); $county = $Geo::Postcodes::U2::county_of($postcode); The county where the postcode is located. This field is not used by danish postcodes. =head2 owner - owner_of $owner = $P->owner(); $owner = $Geo::Postcodes::U2::owner_of($postcode); The owner of the postcode. This value is only used if the postcode is used by a single user. This field is not used by norwegian postcodes. =head2 address - address_of $address = $P->address(); $address = $Geo::Postcodes::U2::address_of($postcode); The street address of the postcode. This value is only used if the postcode is used by a single street, and the street does not use any other posrcode. This field is not used by norwegian postcodes. =head2 type - type_of $type = $P->type(); $type = $Geo::Postcodes::U2::type_of($postcode); The type of the postcode, as a short (2-4 characters) code. The types supported by the core module are: =over =item BX Post Office box =item ST Street address =item SX Service box (as a Post Office box, but the mail is delivered to the customer). =item IO Individual owner (a company with its own postcode). =item STBX Either a Street address (ST) or a Post Office box (BX) =item MU Multiple usage (a mix of the other types) =item PP Porto Paye receiver (mail where the reicever will pay the postage). =item PN Place name =back The child classes can use as many of the codes as they want. Utopian postcodes support them all. =head2 type_verbose - type_verbose_of A textual description of the codes, as specified in the previous section, as the codes themselves are not very user friendly. $utopian_description = $P->type_verbose(); $utopian_description = Geo::postcodes::U2::type_verbose_of($postcode); This will give the description in utopian, if set up by the utopian module, and english otherwise. The individual country classes are responsible for translating the descriptions of the codes they use to the native language, if appropriate. $english_description = Geo::postcodes::type_verbose_of($postcode); $english_description = $P->Geo::Postcodes::type_verbose(); Use the version in the base class for the english version. The danish and norwegian modules have translations for the codes they use. =head1 MAKING UTOPIA The modules can be used as procedures on postcodes, or object oriented. =head2 Example Using Procedures my $postcode = '1010'; if (Geo::Postcodes::U2::valid($postcode)) { printf "Postcode" '%s'.\n", $postcode; printf "Postal location: '%s'.\n", location_of($postcode); printf "Borough: '%s'.\n", borough_of($postcode); printf "County: '%s'.\n", county_of($postcode); printf "Owner: '%s'.\n", owner_of($postcode); printf "Address: '%s'.\n", address_of($postcode); printf "Postcode type: '%s'.\n", type_of($postcode); printf "- in utopian: '%s'.\n", type_of_verbose($postcode); printf "- in english: '%s'.\n", Geo::Postcodes::type_of_verbose($postcode); } The fields are described in the prevoius section; L. =head2 Object Oriented Example if (Geo::Postcodes::U2::valid($postcode)) { my $P = Geo::Postcodes::U2->new($postcode); printf "Postcode '%s'.\n", $P->postcode(); printf "Postal location: '%s'.\n", $P->location(); printf "Borough: '%s'.\n", $P->borough(); printf "County: '%s'.\n", $P->county(); printf "Owner: '%s'.\n", $P->owner(); printf "Address: '%s'.\n", $P->address(); printf "Postcode type: '%s'.\n", $P->type(); printf "- in norwegian: '%s'.\n", $P->type_verbose(); printf "- in english: '%s'.\n", $P->Geo::Postcodes::type_verbose(); } If speed is a concern, use the procedure version. =head2 new my $P = Geo::Postcodes::U2->new($postcode); Create a new postcode object. Internally this will call the C procedures for the fields supported by utopian postcodes. The constructor will return I if given an invalid or illegal postcode. Do not try method calls on it, as it is not an object (and will result in a runtime error). See the description of the I and I procedures above. =head1 COMPACT UTOPIA The test for a valid postcode can also be done on the object itself, as it will be I when passed an illegal or invalid postcode (and thus no object at all.) The example in the prevous section had a line for each field, but it is possible to use a loop instead: if ($P = Geo::Postcodes::U2->new($postcode)) { foreach my $field (Geo::Postcodes::U2::get_fields()) { printf("%-20s %s\n", ucfirst($field), $P->$field()) } } This will B show the english description of the type, and the printed labels are slightly different than in the previous example. =head2 get_fields Use this procedure/method to get a list of the supported fields for utopian postcodes. my @fields = Geo::postcodes::U2::get_fields(); my @fields = $P->get_fields(); =head2 is_field Use this procedure/method to check if the specified field exist for utopian postcodes. my $boolean = Geo::postcodes::U2::is_field($field); my $boolean = $P->is_field($field); =head2 A sample program This sample program is available as "C" in the danish, and "C" in the norwegian distributions. The line numbers are used for clarity only. Specify one or more postcodes on the command line; e.g. "C". 01 #! /usr/bin/perl -w 02 use strict; 03 use Geo::Postcodes::U2 0.30; The example will not work with older versions of the module. 04 unless (@ARGV) 05 { 06 print "Usage: basic_u2 \n"; 07 exit; 08 } Exit with an error message if the program hasn't been given any arguments. 09 foreach my $postcode (@ARGV) 10 { Loop through the arguments, and create a postcode object for each one. 11 if (my $P = Geo::Postcodes::U2->new($postcode))) 12 { Skip the argument if it isn't a valid postcode. The C-call returns an object reference on success, and I on failure (i.e. an illegal or unvalid postcode). 13 foreach my $field (Geo::Postcodes::U2::get_fields()) 14 { 15 printf("%-10s\t%s\n", ucfirst($field), $P->$field() || ""), 16 } For each field supported by the module, we print the field name (with an initial uppercase letter), followed by the value of the field. All tabulated nicely. 17 printf("%-10s\t%s\n\n", "Type_english", 18 Geo::Postcodes::type2verbose($P->type())); 19 } We must ask for the I description of the type manually. 20 else # Not valid. 21 { 22 if (Geo::Postcodes::U2::legal($postcode)) 23 { 24 print "Postcode '$postcode' not in use.\n\n"; 25 } 26 else 27 { 28 print "Illegal postcode '$postcode'.\n\n"; 29 } 30 } 31 } This part will be called if the C-call fails, and we will get an error message telling us what is wrong; if the argument is illegal (not following the rules for utopian postcodes) or invalid (not in use). =head1 ADVANCED UTOPIA The procedures and methods mentioned till now will only give us one (or zero) postcode at a time, but it is possibly to get I at once. =head2 get_postcodes @postcodes = Geo::postcodes::U2::get_postcodes(); # Unsorted @postcodes = sort Geo::postcodes::U2::get_postcodes(); # Sorted This procedure returns an unsorted list of all the postcodes. It is possible to use this call to write your own selection code: my @list; foreach my $postcode (Geo::postcodes::U2::get_postcodes()) { push(@list, $postcode) if check_the_postcode_for_something($postcode); } Write the C-procedure to decide if the postcode should be included. Use the C-procedures, or whatever else is needed. Do I create postcode objects inside this loop, as this will increase the time of execution quite a lot. =head2 selection The module has a selection procedure/method, that can be used if the check can be expressed as a regular expression on one or more if the fields. See the selection manual (I or I) for further information. =head2 selection_loop This procedure/method can be used to get rid of the loop in the following example: my @list = Geo::postcodes::U2::selection(....); foreach my $postcode (@list) { do_something($postcode) } The following line of code will do the same thing: Geo::postcodes::U2::selection_loop(\&do_something, ....); The loop can use postcode objects instead of plain postcodes, as with L. Geo::postcodes::U2->selection_loop(\&do_something, ....); The benefit of this is that the C-method will generate all the postcode objects, before passing them on, while this method will generate one at a time, destroying the prevoius one before creating a new. =head2 verify_selectionlist This will check the list of arguments for correctness, and should be used before calling C or C. The procedure returns a modified version of the arguments on success, and diagnostic messages on failure. my ($status, @modified) = Geo::Postcodes::U2::verify_selectionlist(@args); if ($status) { my @result = Geo::Postcodes::U2::selection(@modified); # And do something with the list of postcodes. } else { print "Diagnostic messages:\n"; map { print " - $_\n" } @modified; } =head2 A second program This sample program is available as "C" in the danish, and "C" in the norwegian distributions. The line numbers are used for clarity only. Specify a field and a value on the command line, e.g. "C". 01 #! /usr/bin/perl -w 02 use strict; 03 use Geo::Postcodes::DK 0.30; 04 unless (@ARGV == 2) 05 { 06 print "Usage: selection_u2 \n"; 07 print "Legal fields: ", join(" ", Geo::Postcodes::U2::get_fields()), ".\n"; 08 exit; 09 } This program requires exactly two arguments, a field and a value, and is terminated if the are missing. 10 my $field = shift(@ARGV); 11 my $value = shift(@ARGV); 12 my @fields; 13 if (Geo::Postcodes::U2::is_field($field)) 14 { Do we have a legal field? (If not, the C-part below will give an error message. 15 @fields = Geo::Postcodes::U2::get_fields(); Get the list of available fields for this class. 16 foreach my $m (@fields) 17 { 18 printf("%-14s", ucfirst($m)); 19 } 20 print "\n"; We are going to print one line for each matching postcode, and this will give us a header line. 21 Geo::Postcodes::U2->selection_loop(\&print_it, $field, $value); This piece of magic will use the C