Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Geo::Postcodes::TutoriUser)Contributed Perl DocumenGeo::Postcodes::Tutorial(3)

       Geo::Postcodes::Tutorial	- How to use the Geo::Postcodes::* modules

	use Geo::Postcodes::U2;

	my $postcode = '1104';
	my $location = Geo::Postcodes::U2::location_of($postcode);

       This tutorial uses the fictious country Utopia (with country code
       'U2'), and the rest of this document will refer to the non-existent
       module "Geo::Postcodes::U2". Any	differences with the two existing
       country modules ("Geo::Postcodes::DK"; Denmark and
       "Geo::Postcodes::NO"; Norway) are explained.

       The latest version of Geo::Postcodes::U2	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 Geo::Postcodes as	well.

	shell> perl -MCPAN -e shell
	cpan> install Geo::Postcodes::U2

       It may be possible to use the command "cpan" instead of the first line.

       Include the following line in the program, after	installing the module:

	use Geo::Postcodes::U2;

       Use the legal 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

       The procedure valid 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

       Utopian postcodes support all the 8 fields set up by the	core module.
       Every field is available	as "$P->xxx" or	"xxx_of($postcode)", where
       "xxx" is	the field name.	The procedures/methods will return undef if
       the value is unspecified	for the	given postcode.

   postcode - postcode_of
	$postcode = $P->postcode();
	$postcode = Geo::Postcodes::U2::location_of($postcode);	# Silly

       The actual postcode value is available with "postcode" method, as the
       object itself does not have this	information. The corresponding
       postcode_of-procedure is	used internally	by selection-procedure/method,
       but should be avoided in	applications.

   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.

   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.

   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.

   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.

   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.

   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:

       BX  Post	Office box

       ST  Street address

       SX  Service box (as a Post Office box, but the mail is delivered	to the

       IO  Individual owner (a company with its	own postcode).

	   Either a Street address (ST)	or a Post Office box (BX)

       MU  Multiple usage (a mix of the	other types)

       PP  Porto Paye receiver (mail where the reicever	will pay the postage).

       PN  Place name

       The child classes can use as many of the	codes as they want. Utopian
       postcodes support them all.

   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

	$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

       The modules can be used as procedures on	postcodes, or object oriented.

   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; "UTOPIAN FIELDS".

   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.

	my $P =	Geo::Postcodes::U2->new($postcode);

       Create a	new postcode object. Internally	this will call the "xxx_of"
       procedures for the fields supported by utopian postcodes.

       The constructor will return undef 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 legal and
       valid procedures	above.

       The test	for a valid postcode can also be done on the object itself, as
       it will be undef	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 not show the english description of the type, and the printed
       labels are slightly different than in the previous example.

       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();

       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);

   A sample program
       This sample program is available	as ""eg/basic_dk"" in the danish, and
       ""eg/basic_no"" in the norwegian	distributions. The line	numbers	are
       used for	clarity	only.

       Specify one or more postcodes on	the command line; e.g. ""basic_u2 1001

	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 <one or more utopian postcodes>\n";
	07   exit;
	08 }

       Exit with an error message if the program hasn't	been given any

	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 "new"-call returns
       an object reference on success, and undef 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 english 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 "new"-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).

       The procedures and methods mentioned till now will only give us one (or
       zero) postcode at a time, but it	is possibly to get several postcodes
       at once.

	 @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 "check_the_postcode_for_something"-procedure to decide	if the
       postcode	should be included. Use	the "xxx_of"-procedures, or whatever
       else is needed. Do not create postcode objects inside this loop,	as
       this will increase the time of execution	quite a	lot.

       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

       See the selection manual	(perldoc Geo::Postcodes::Selection or man
       Geo::Postcodes::Selection) for further information.

       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)

       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

	 Geo::postcodes::U2->selection_loop(\&do_something, ....);

       The benefit of this is that the "selection"-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

       This will check the list	of arguments for correctness, and should be
       used before calling "selection" or "selection_loop". 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.
	   print "Diagnostic messages:\n";
	   map { print " - $_\n" } @modified;

   A second program
       This sample program is available	as ""eg/selection_dk"" in the danish,
       and ""eg/selectionc_no""	in the norwegian distributions.	The line
       numbers are used	for clarity only.

       Specify a field and a value on the command line,	e.g.  ""selection_u2
       postcode	%12"".

	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 <field> <value>\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 "else"-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	"select" method	to find	any matching
       postcodes, and pass them	on as a	postcode pbject	to the specified
       "print_it" procedure - one at a time.

	22   print "\n";
	23 }

	24 else	# illegal field.
	25 {
	26   print "Not	a legal	field '$field'.\n";
	27 }

       A simple	error message.

	28 sub print_it
	29 {
	30   my	$object	= shift;
	31   foreach my	$method	(@fields)
	32   {
	33     printf("%-14s", $object->$method() || "");
	34   }
	35   print "\n";
	36 }

       This procedure is called	for each matching postcode, and	receives a
       postcode	object as argument. The	"foreach" loop uses the	list of	fields
       set up in line 15. The second part of the argument in the "print"
       statement traps errors, as the call returns undef if the	value is
       undefined for the given postcode, and printing an undefined value gives
       a warning.

   A third program
       This sample program is available	as ""eg/multiselection_dk"" in the
       danish, and ""eg/multiselectionc_no"" in	the norwegian distributions.
       The line	numbers	are used for clarity only.

       Specify a field and a value on the command line,	e.g.
       ""multiselection_u2 postcode %12"" (for postcodes ending	with '12').

	01 #! /usr/bin/perl -w
	02 use strict;
	03 use Geo::Postcodes::U2 0.30;

       This should be familiar by now.

	04 my ($status,	@lines)	= Geo::Postcodes::U2::verify_selectionlist(@ARGV);

       Simply passing a	list of	arguments on to	"selection" is not a good
       idea, as	it will	return an empty	list both on failure (as in syntax
       errors, illegal modes or	fields)	and when the call itself didn't	match

       Use "verify_selectionlist" to check the argument	list for errors. The
       $status variable	is true	if the argument	list is	legal, and false

	11 if ($status == 0)
	12 {
	13   print "Usage: \n",
	14	   " * multiselection_u2 [all|none]\n",
	15	   " * multiselection_u2 [" ,
	16	   join("|", Geo::Postcodes::get_initial_selectionmodes()),
	17	   "]? <field> <value> [[",
	18	   join("|", Geo::Postcodes::get_selectionmodes()),
	19	   "]? [<field>	<value>]]*\n\n";
	20   print "Legal fields: ", join(", ",	Geo::Postcodes::U2::get_fields()), "\n\n";

       We use several procedures to show the legal modes and fields. This
       ensures that we do not have to update the program if we add new modes
       or fields in the	modules	later on (and that the code, as	shown, will
       work for	all country modules; after substituting	'U2' and 'u2' with
       another country code.)  ).

	21   print "Diagnostic output:\n";
	22   foreach (@lines)
	23   {
	24     print " * $_\n";
	25   }

       The @lines variable contains diagnostic output on failure, and they are
       printed as a service to the user	- to help correct the error.

	26   exit;
	27 }

	28 my @fields =	Geo::Postcodes::U2::get_fields();
	29 foreach my $m (@fields)
	30 {
	31   printf("%-14s", ucfirst($m)); # Print headers for each column
	32 }
	33 print "\n";

	34 foreach my $P (Geo::Postcodes::U2->selection(@lines))
	35 {

       Note that we use	the argument list as returned by the
       "verify_selectionlist" call, as it corrects some	mistakes that the
       "selection" procedure/method does not cope with.

	36   foreach my	$method	(@fields)
	37   {
	38     printf("%-14s", $P->$method() ||	"");
	39   }
	40   print "\n";
	41 }
	42 print "\n";

   Advanced selection
       The arguments to	the selection procedure/method is not restricted to
       pairs of	field/value, combined together with the	logical	operators
       'and', 'or' and so on.

       It is also possible to call external procedures,	and have them decide
       if the postcode should be included. Specify 'procedure' and
       "\&procedure_to_do_the_job", instead of a field/value pair.

       The procedure is	passed the postcode, and must return true or false.

	sub procedure_to_do_the_job
	  my postcode =	shift;
	  return 1 if ...
	  return 0;

       Passing a pointer to a non-existing procedure to	selection will result
       in an empty list	in return. verify_selectionlist	can be used to check
       that any	specified procedures actually exist.

   A fourth program
       This sample program is available	as ""eg/static_dk"" in the danish, and
       ""eg/static_no""	in the norwegian distributions.	The line numbers are
       used for	clarity	only.

	01 #! /usr/bin/perl -w
	02 use strict;
	03 use Geo::Postcodes::U2 0.30;

       This should be familiar by now.

	04 use Digest::SHA1;

       For the sake of this example, som computation had to be done that could
       not be done by a	regular	expression. This module	was chosen.

	05 my @arg1 = ('postcode' => '(.)(.)\2\1');

       We start	with a regular expression, matching postcodes where the	first
       and fourth digit	are identical, as is the second	and third.

	06 print "All norwegian	postcodes where	(...),\n";
	06 print "All norwegian	postcodes where	:\n";
	07 my @postcodes = Geo::Postcodes::NO::selection(@arg1);
	08 print join ",", @postcodes; print ".\n\n";

       This prints the matching	postcodes. Nothing fancy so far.

	09 print "As above, but	with the addition of a procedure:\n";
	10 my @arg2 = (@arg1, 'procedure' => \&selector_procedure);

       Now we have added a procedure to	the argument list, and the selection
       call below does the job for us.

	11 @postcodes =	Geo::Postcodes::NO::selection(@arg2);
	12 print join ",", @postcodes; print ".\n\n";

	13 sub selector_procedure
	14 {
	15   my	$postcode = shift;
	16   my	$location = Geo::Postcodes::NO::location_of($postcode);
	17   my	$digest	= Digest::SHA1::sha1($location);
	18   return 1 if substr($digest, 10, 5)	=~ /[a-z]/;
	19   return 0;
	20 }

       The procedure computes the SHA1-digest for the postal location, and
       returns true if the there is a lower case letter	(a-z) among the	11th
       to 15th characters of the digest. This may not be very useful in

       See also	the documentation for the core module Geo::Postcodes, the
       selection family	(perldoc Geo::Postcodes::Selection or man
       Geo::Postcodes::Selection) and the individual country modules;
       currently Geo::Postcodes::DK (Denmark) and Geo::Postcodes::NO (Norway).

       The latest version of everyting is available on CPAN, but see also the
       library home page; for	additional
       information and sample usage.

       Copyright (C) 2006 by Arne Sommer -

       This library is free software; you can redistribute them	and/or modify
       it under	the same terms as Perl itself.

perl v5.32.0			  2006-10-01	   Geo::Postcodes::Tutorial(3)


Want to link to this manual page? Use this URL:

home | help