This is Info file pm.info, produced by Makeinfo version 1.68 from the
input file bigpm.texi.


File: pm.info,  Node: Class/Mutator,  Next: Class/NamedParms,  Prev: Class/Multimethods,  Up: Module List

SYNOPSIS
========

DESCRIPTION
===========

   Class::Mutator adds the power of 'dynamic polymorphism' to Perl objects,
its similar to Michael Schwern's Sex.pm which he was working on around the
same time, only a little bit more predictable.

   Any object that inherits Class::Mutator principally gains two new
methods, mutate and unmutate that allows them to add methods to themselves
at runtime from other packages. With most recently mutated packages having
precedence when methods are defiend in more than one package.

   This module came about while i was doing some training at the BBC and
someone asked how you could do this easily, after discussion with my fellow
London.pm'ers in particular Piers Cawley this module came about.

TODO
====

   Lots to be done at the minute it requires the extremely useful Memoize
module, this module as always allows be to increase performance without
having to think i'm going to write some code that retains performance if
Memoize is not installed.

   I'm also going to take Michael Schwern's idea of Sex.pm choosing method
precendence randomly and write an Agent::Sex on top of Steve Purkis' Agent
framework so we can start to do some evolutionary Agents in Perl.

METHODS
=======

build_mutation_package(@package_names)
--------------------------------------

   Builds the new mutation package.

build_package_list(operation,package)
-------------------------------------

   Builds a new package list based on the current packages list and the
operation and package (the operation is upon) handed to this method.

unmutate
--------

   Remove mutation abilities via a package

mutate
------

   Adds a mutation.

AUTHOR
======

   Greg McCarroll (greg@mccarroll.demon.co.uk)


File: pm.info,  Node: Class/NamedParms,  Next: Class/ObjectTemplate,  Prev: Class/Mutator,  Up: Module List

A lightweight named parameter handling system.
**********************************************

NAME
====

   Class::NamedParms - A lightweight named parameter handling system.

SYNOPSIS
========

     package SomePackage;
     use Class::NamedParms;
     use vars qw (@ISA);
     @ISA=qw(Class::NamedParms);

     sub new {

     my ($proto) = shift;
         my ($class) = ref ($proto) || $proto;
     
         $self = Class::NamedParms->new(-benefits,-costs);
     $self = bless $self,$class;

     $self;
      }

     $thingy = SomePackage->new;
     $thingy->set({ -benefits => 1, -costs => 0.5 });
     my ($costs,$benefits) = $thingy->get(-costs,-benefits);

DESCRIPTION
===========

   Provides key name checking for named accessor parameters. This allows
the use of a generic 'get/set' type parameterized accessor while
automatically catching accidental mis-spellings and usage of uninitialized
parameters. This catches a large class of programming errors without
requiring a new accessor for every object parameter.

CHANGES
=======

     1.00 1999.06.16 - Initial release.

     1.01 1999.06.17 - Bug fix to 'clear' method. Added 'make test' support.

     1.02 1999.06.18 - Performance tweak to 'get' method.

     1.03 1999.06.21 - Minor docs tweaks. Removal of 'use attrs' for portability

     1.04 1999.10.08 - Bug fix to 'all_parms' method

Initialization
--------------

new;
     Creates a new instance of a NamedParms object.

     You can optionally 'declare' the legal parameter keys at the same
     time.

     Example:

          my $self = Class::NamedParms(-benefits,-costs,-other);

`list_declared_parms;'
     Returns a list of all parm names that have been declared for this
     NamedParms object. List is unsorted.

`list_initialized_parms;'
     Lists all parms that have had values initialized for this NamedParms
     object Returns a list of the parameter names. List is unsorted.

`declare($parmname,[$parmname1,...]);'
     Declares one or more parameters for use with the NamedParms object.

     Example:

          $self->declare(-moved_in,-car_key,-house_key,-relationship);

     This *does not* initialize the parameters - only declares them to be
     legal for use.

`undeclare($parmname,$parmname1,...);'
     'undeclares' one or more parameters for use with the NamedParms
     object.  This also deletes any values assigned to those parameters.

     Example:

          $self->undeclare(-house_key,-car_key,-relationship);

`exists($parmname);'
     Returns true if the specified parmname has been initialized via 'set'.

`set($parm_ref);'
     Sets one or more named parameter values.

     Example:

          $self->set({ -thingy => 'test', -other_thingy => 'more stuff' });

     Will 'confess' if an attempt is made to set an undeclared parameter
     key.

`clear(@parm_names);'
     Clears (deletes) one or more named parameter values.

     Example:

          $self->clear(-this,-that,-the_other_thing);

     Note: A 'cleared' value returns undef from 'get'.

`get(@parm_names);'
     Gets one or more named parameter values.

     Screams and dies (well, 'confess'es) if you attempt to read a value
     that has not been initialized. Results are returned in the same order
     as the parameter names passed.

     In a scalar context, the _last_ result is what is returned.

     Example:

          my ($age,$gender) = $self->get(-age,-gender);

     Will 'confess' if an attempt is made to access an undeclared key or if
     the requested value has not been initialized.

`all_parms;'
     Returns an anonymous hash containing all the currently set keys and
     values. This hash is suitable for usage with Class::NamedParms or
     Class::ParmList for setting keys/values with their 'set' methods.

     It works by making a shallow copy of the data. This means that it
     copies the scalar values.  In the case of simple numbers and strings,
     this produces a new copy, in the case of references to hashes and
     arrays or objects, it returns the reference to the original object
     such that alterations of the returned object are reflected in the
     live copy.

     Example:

          my $parms = $parms->all_parms;

COPYRIGHT
=========

   Copyright 1999, Benjamin Franz (<URL:http://www.nihongo.org/snowhare/>)
and FreeRun Technologies, Inc. (<URL:http://www.freeruntech.com/>). All
Rights Reserved.  This software may be copied or redistributed under the
same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

VERSION
=======

     1.04

TODO
====

   Debugging.


File: pm.info,  Node: Class/ObjectTemplate,  Next: Class/ObjectTemplate/DB,  Prev: Class/NamedParms,  Up: Module List

SYNOPSIS
========

     package Foo;
     use Class::ObjectTemplate;
     require Exporter;
     @ISA = qw(Class::ObjectTemplate Exporter);

     attributes('one', 'two', 'three');

DESCRIPTION
===========

   Class::ObjectTemplate is a utility class to assist in the building of
other Object Oriented Perl classes.

   It was described in detail in the O\'Reilly book, "Advanced Perl
Programming" by Sriram Srinivasam.

EXPORT
------

   attributes()

AUTHOR
======

   Original code by Sriram Srinivasam.

   Fixes and CPAN module by Jason E. Stewart (jason@openinformatics.com)

SEE ALSO
========

   http://www.oreilly.com/catalog/advperl/

   perl(1).


File: pm.info,  Node: Class/ObjectTemplate/DB,  Next: Class/ParamParser,  Prev: Class/ObjectTemplate,  Up: Module List

Perl extension for an optimized template builder base class with lookup capability.
***********************************************************************************

NAME
====

   Class::ObjectTemplate:DB - Perl extension for an optimized template
builder base class with lookup capability.

SYNOPSIS
========

     package Foo;
     use Class::ObjectTemplate::DB;
     require Exporter;
     @ISA = qw(Class::ObjectTemplate:DB Exporter);

     attributes(lookup => ['one', 'two'], no_lookup => ['three']);

     $foo = Foo->new();

     # these two invocations can trigger lookup
     $val = $foo->one();
     $val = $foo->two();

     # this invocation will not trigger lookup
     $val = $foo->three();

     # undefined() handles lookup
     sub Foo::undefined {
       my ($self,$attr) = @_;

     # we retrieve $attr from DB
     return DB_Lookup($self,$attr);
       }

DESCRIPTION
===========

   Class::ObjectTemplate::DB extends Class::ObjectTemplate in one simple
way: the `undefined()' method.

   When a class that inherits from Class::ObjectTemplate::DB defines a
method called undefined(), that method will be triggered when an
attribute\'s getter method is invoked and the attribute\'s current value
is undef.

   The author finds this useful when representing classes based on objects
stored in databases (hence the name of the module). That way an object can
be created, without triggering a DB lookup. Later if data is accessed and
it is not currently present in the object, it can be retrieved on an
as-need basis.

METHODS
-------

attributes('attr1', 'attr2')
attributes(lookup => ['attr1'], no_lookup => ['attr2'])
     attributes() still supports the standard Class::ObjectTemplate syntax
     of a list of attribute names.

     To use the new functionality, the new key-value syntax must be used.
     Any method names specified in the lookup array, will trigger
     undefined. Those specified in the `no_lookup' will not trigger
     `undefined()'.

undefined($self, $attr_name)
     A class that inherits from Class::ObjectTemplate::DB must define a
     method called `undefined()' in order to utilize the lookup behavior.

     Whenever an attribute\'s getter method is invoked, and that
     attribute\'s value is currently undef, then `undefined()' will be
     invoked if that attribute was defined as in the lookup array when
     attributes() was called.

     A class\'s `undefined()' method can include any specialized code
     needed to lookup the value for that objects\'s attribute, such as
     using DBI to connect to a local DB, and retrieve the value from a
     table.

     Class::ObjectTemplate::DB defines a default `undefined()' which does
     nothing.

EXPORT
------

attributes()
AUTHOR
======

   Jason E. Stewart (jason@openinformatics.com)

SEE ALSO
========

   perl(1).


File: pm.info,  Node: Class/ParamParser,  Next: Class/ParmList,  Prev: Class/ObjectTemplate/DB,  Up: Module List

Provides complex parameter list parsing.
****************************************

NAME
====

   Class::ParamParser - Provides complex parameter list parsing.

DEPENDENCIES
============

Perl Version
------------

     5.004

Standard Modules
----------------

     I<none>

Nonstandard Modules
-------------------

     I<none>

SYNOPSIS
========

     use Class::ParamParser;
     @ISA = qw( Class::ParamParser );

PARSING PARAMS INTO NAMED HASH
------------------------------

     sub textfield {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0,
     		[ 'name', 'value', 'size', 'maxlength' ],
     		{ 'default' => 'value' } );
     	$rh_params->{'type'} = 'text';
     	return( $self->make_html_tag( 'input', $rh_params ) );
     }

     sub textarea {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0,
     		[ 'name', 'text', 'rows', 'cols' ], { 'default' => 'text',
     		'value' => 'text', 'columns' => 'cols' }, 'text', 1 );
     	my $ra_text = delete( $rh_params->{'text'} );
     	return( $self->make_html_tag( 'textarea', $rh_params, $ra_text ) );
     }

     sub AUTOLOAD {
     	my $self = shift( @_ );
     	my $rh_params = $self->params_to_hash( \@_, 0, 'text', {}, 'text' );
     	my $ra_text = delete( $rh_params->{'text'} );
     	$AUTOLOAD =~ m/([^:]*)$/;
     	my $tag_name = $1;
     	return( $self->make_html_tag( $tag_name, $rh_params, $ra_text ) );
     }

PARSING PARAMS INTO POSITIONAL ARRAY
------------------------------------

     sub property {
     	my $self = shift( @_ );
     	my ($key,$new_value) = $self->params_to_array(\@_,1,['key','value']);
     	if( defined( $new_value ) ) {
     		$self->{$key} = $new_value;
     	}
     	return( $self->{$key} );
     }

     sub make_html_tag {
     	my $self = shift( @_ );
     	my ($tag_name, $rh_params, $ra_text) =
     		$self->params_to_array( \@_, 1,
     		[ 'tag', 'params', 'text' ],
     		{ 'name' => 'tag', 'param' => 'params' } );
     	ref($rh_params) eq 'HASH' or $rh_params = {};
     	ref($ra_text) eq 'ARRAY' or $ra_text = [$ra_text];
     	return( join( '',
     		"<$tag_name",
     		(map { " $_=\"$rh_params->{$_}\"" } keys %{$rh_params}),
     		">",
     		@{$ra_text},
     		"</$tagname>",
     	) );
     }

DESCRIPTION
===========

   This Perl 5 object class implements two methods which inherited classes
can use to tidy up parameter lists for their own methods and functions.
The two methods differ in that one returns a HASH ref containing named
parameters and the other returns an ARRAY ref containing positional
parameters.

   Both methods can process the same kind of input parameter formats:


     *empty list*


     value


     value1, value2, ...


     name1 => value1, name2 => value2, ...


     -name1 => value1, -NAME2 => value2, ...


     { -Name1 => value1, NAME2 => value2, ... }


     { name1 => value1, -Name2 => value2, ... }, valueR


     { name1 => value1, -Name2 => value2, ... }, valueR1, valueR2, ...

   Those examples included single or multiple positional parameters,
single or multiple named parameters, and a HASH ref containing named
parameters (with optional "remaining" values afterwards).  That list of
input variations is not exhaustive.  Named parameters can either be
prefixed with "-" or left natural.

   We assume that the parameters are named when either they come as a HASH
ref or the first parameter begins with a "-".  We assume that they are
positional if there is an odd number of them.  Otherwise we are in doubt
and rely on an optional argument to the tidying method that tells us which
to guess by default.

   We assume that any "value" may be an array ref (aka "multiple" values
under the same name) and hence we don't do anything special with them,
passing them as is.  The only exception to this is with "remaining"
values; if there is more than one of them and the first isn't an array
ref, then they are all put in an array ref.

   If the source and destination are both positional, then they are
identical.

SYNTAX
======

   This class does not export any functions or methods, so you need to
call them using object notation.  This means using *Class->function()* for
functions and *$object->method()* for methods.  If you are inheriting this
class for your own modules, then that often means something like
*$self->method()*.  Note that this class doesn't have any properties of
its own.

FUNCTIONS AND METHODS
=====================

params_to_hash( SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
-----------------------------------------------------------

   See below for argument descriptions.

params_to_array( SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
------------------------------------------------------------

   See below for argument descriptions.

params_to_hash_or_array( TO, SOURCE, DEF, NAMES[, RENAME[, REM[, LC]]] )
------------------------------------------------------------------------

   This bonus third method is used internally to implement the first two.
It has an extra first argument, TO, which causes an Array ref to be
returned when true and a Hash ref to be returned when false; the default
value is false.

ARGUMENTS
=========

   The arguments for the above methods are the same, so they are discussed
together here:

  1. The first argument, SOURCE, is an ARRAY ref containing the original
     parameters that were passed to the method which calls this one.  It
     is safe to pass "\@_" because we don't modify the argument at all.
     If SOURCE isn't a valid ARRAY ref then its default value is [].

  2. The second argument, DEF, is a boolean/scalar that tells us whether,
     when in doubt over whether SOURCE is in positional or named format,
     what to guess by default.  A value of 0, the default, means we guess
     named, and a value of 1 means we assume positional.

  3. The third argument, NAMES, is an ARRAY ref (or SCALAR) that provides
     the names to use when SOURCE and our return value are not in the same
     format (named or positional).  This is because positional parameters
     don't know what their names are and named parameters (hashes) don't
     know what order they belong in; the NAMES array provides the missing
     information to both.  The first name in NAMES matches the first value
     in a positional SOURCE, and so-on.  Likewise, the order of argument
     names in NAMES determines the sequence for positional output when the
     SOURCE is named.

  4. The optional fourth argument, RENAME, is a HASH ref that allows us to
     interpret a variety of names from a SOURCE in named format as being
     aliases for one enother.  The keys in the hash are names to look for
     and the values are what to rename them to.  Keys are matched
     regardless of whether the SOURCE names have "-" in front of them or
     not.  If several SOURCE names are renamed to the same hash value, then
     all but one are lost; the SOURCE should never contain more than one
     alias for the same parameter anyway.  One way to explicitely delete a
     parameter is to rename it with "", as parameters with that name are
     discarded.

  5. The optional fifth argument, REM, is only used in circumstances where
     the first element of SOURCE is a HASH ref containing the actual named
     parameters that SOURCE would otherwise be.  If SOURCE has extra,
     "remaining" elements following the HASH ref, then REM says what its
     name is.  Remaining parameters with the same name as normal
     parameters (post renaming and "-" substitution) take precedence.  The
     default value for REM is "", and it is discarded unless renamed.
     Note that the value returned with REM can be either a single scalar
     value, when the "remaining" is a single scalar value, or an array
     ref, when there are more than one "remaining" or the first
     "remaining" is an array ref (passed as is).

  6. The optional sixth argument, LC, is a boolean/scalar that forces
     named parameters in SOURCE to be lowercased; by default this is
     false, meaning that the original case is preserved.  Use this when
     you want your named parameters to have case-insensitive names, for
     accurate matching by your own code or RENAME.  If you use this, you
     must provide lowercased keys and values in your RENAME hash, as well
     as lowercased NAMES and REM; none of these are lowercased for you.


AUTHOR
======

   Copyright (c) 1999-2001, Darren R. Duncan. All rights reserved. This
module is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.  However, I do request that this copyright
information remain attached to the file.  If you modify this module and
redistribute a changed version then please attach a note listing the
modifications.

   I am always interested in knowing how my work helps others, so if you
put this module to use in any of your own code then please send me the
URL.  Also, if you make modifications to the module because it doesn't
work the way you need, please send me a copy so that I can roll desirable
changes into the main release.

   Address comments, suggestions, and bug reports to
*perl@DarrenDuncan.net*.

SEE ALSO
========

   perl(1).


File: pm.info,  Node: Class/ParmList,  Next: Class/Phrasebook,  Prev: Class/ParamParser,  Up: Module List

A collection of routines for processing named parameter lists for method calls.
*******************************************************************************

NAME
====

   Class::ParmList - A collection of routines for processing named
parameter lists for method calls.

SYNOPSIS
========

     use Class::ParmList qw(simple_parms parse_parms);

     $thingy->some_method({
          -bgcolor   => '#ff0000',
          -textcolor => '#000000'
     	  });

     sub some_method {
         my ($self) = shift;

     my ($parm_ref) = @_;

     my $parms = Class::ParmList->new ({
            -parms    => $parm_ref,
            -legal    => [qw (-textcolor -border -cellpadding)],
            -required => [qw (-bgcolor)],
            -defaults => {
                           -bgcolor   => "#ffffff",
                           -textcolor => "#000000"
                         }
         });

     if (not defined $parms) {
     	    my $error_message = Class::ParmList->error;
     		die ($error_message);
     }

     # Stuff...

     }

     sub another_method {
       my $self = shift;
       my ($name,$rank,$serial_number) = simple_parms([qw(-name -rank -serial_number)], @_);

     #...
       }

     sub still_another {
        my $parms = parse_parms ({
               -parms    => \@_,
               -legal    => [qw (-textcolor -border -cellpadding)],
               -required => [qw (-bgcolor)],
               -defaults => {
                              -bgcolor   => "#ffffff",
                              -textcolor => "#000000"
                            }
            });
        if (not defined $parms) {
     	    my $error_message = Class::ParmList->error;
     		die ($error_message);
        }

     # ...
       }

DESCRIPTION
===========

   This is a simple package for validating calling parameters to a
subroutine or method. It allows you to use "named parameters" while
providing checking for number and naming of parameters for verifying
inputs are as expected and meet any minimum requirements. It also allows
the setting of default values for the named parameters if omitted.

CHANGES
=======

     1.00 1999.06.16 - Initial release

     1.01 1999.06.18 - Performance tweaks

     1.02 1999.06.21 - Fixing of failure to catch undeclared parm,
                       removal of 'use attrs qw(method)', and
     				   extension of 'make test' support.

     1.03 2000.12.06 - Added exportable class functions 'simple_parms'
                       and 'parse_parms' and allowed 'stacking' references
                       for parms to the object to improve calling usage.

METHODS
=======

`new($parm_list_ref);'
     Returns a reference to an object that can be used to return values.
     If an improper specification is passed, returns 'undef'.  Otherwise
     returns the reference.

     Example:

          my $parms = Class::ParmList->new ({
                 -parms    => $parm_ref,
                 -legal    => [qw (-textcolor -border -cellpadding)],
                 -required => [qw (-bgcolor)],
                 -defaults => {
                                -bgcolor   => "#ffffff",
                                -textcolor => "#000000"
                              }
              });
          All four parameters (-parms, -legal, -required, and -defaults) are
          optional. It is liberal in that anything defined for a -default
          or -required is automatically added to the '-legal' list.

     If the '-legal' parameter is not _explicitly_ called out, no checking
     against the legal list is done. If it _is_ explicitly called out,
     then all -parms are checked against it and it will fail with an error
     if a -parms parameter is present but not defined in the -legal
     explict or implict definitions.

     To simplify calling routines, the '-parms' parameters is allowed to
     'stack' anon list references: [['parm','value']]

     This gives a calling routine the ability to parse @_ without jumping
     through hoops to handle the cases of arrays vs hashes for the passed
     parameters.

     Example:

          sub example_sub {
            my $parms = Class::ParmList->new({ -parms => \@_,
                                              -legal => [],
                                           -required => ['-file','-data'],
                                           -defaults => {},
                                           });

          #...
           }

     This routine would accept *either*

          example_sub({ '-file' => 'test', '-data' => 'stuff' });

     or

          example_sub( '-file' => 'test', '-data' => 'stuff' );

     with no code changes.

`parse_parms($parm_list_ref);'
     This is a functional equivalent to the 'new' method. Calling
     parameters are identical, but it is called as a function that may be
     exported.

     Example:

          my $parms = parse_parms({ -parms => \@_,
                                    -legal => [],
                                 -required => ['-file','-data'],
                                 -defaults => {},
                                });

`get($parm_name1,$parm_name2,...);'
     Returns the parameter value(s) specified in the call line. If a
     parameter is not defined, it returns undef. If a set of '-legal'
     parameters were declared, it croaks if a parameter not in the
     '-legal' set is asked for.

     Example:   my ($help,$who) = $parms->get(-help,-who);

`exists($parm_name);'
     Returns true if the parameter specifed by $parm_name (qv.  has been
     initialized), false if it does not exist.

          if ($parms->exists(-help) {
              # do stuff
          }

`list_parms;'
     Returns the list of parameter names. (Names are always presented in
     lowercase).

     Example:

          my (@parm_names) = $parms->list_parms;

`all_parms;'
     Returns an anonymous hash containing all the currently set keys and
     values. This hash is suitable for usage with Class::NamedParms or
     Class::ParmList for setting keys/values. It works by making a shallow
     copy of the data. This means that it copies the scalar values.  In
     the case of simple numbers and strings, this produces a new copy, in
     the case of references to hashes and arrays or objects, it returns
     the references to the original objects.

     Example:

          my $parms = $parms->all_parms;

FUNCTIONS
=========

   ################################################################

error;
     Returns the error message for the most recent invokation of 'new'.
     (Static method - does not require an object to function)

     Example:

          my $error_message = Class::ParmList->error;
          die ($error_message);

`simple_parms(['-list','-of','-parameter_names'],@_);'
     Parses the passed named parameter list (croaking/confessing if extra
     or missing parameters are found).

     Examples:

          use Class::ParmList qw(simple_parms);

          sub some_method {
             my $self = shift;

          my ($name,$rank) = simple_parms([qw(-name -rank)],@_);
          # Now do stuff
           }

          sub some_function {
             my $serial_number = simple_parms([qw(-serial_number)],@_);
             # Now do stuff
          }

     The passed parameter values for parsing this way may be either an
     anonymous hash of parameters

     Example:    a_function({ -parm1_name => $parm1_value, -parm2_name =>
     $parm2_value }) )

     or a straight list of parameters:

     Example:   a_function(-parm1_name => $parm1_value, -parm2_name =>
     $parm2_value) )

     Note that it *IS* legal for a parameter to be passed with an 'undef'
     value - it will not trigger an error.

     If you need optional parameters, this function is not well suited.
     You should use the object methods above instead for that case - they
     are much more flexible (but quite a bit slower and slightly more
     complex to use).

     Its main virtues are that is is simple to use, has rugged error
     checking for mis-usages and is reasonably fast.

     'simple_parms' can be exported by specifying it on the 'use' line.

VERSION
=======

   1.03 2000.12.06

COPYRIGHT
=========

   Copyright 1999,2000 Benjamin Franz
(<URL:http://www.nihongo.org/snowhare/>) and FreeRun Technologies, Inc.
(<URL:http://www.freeruntech.com/>). All Rights Reserved.  This software
may be copied or redistributed under the same terms as Perl itelf.

AUTHOR
======

   Benjamin Franz

TODO
====

   Everything.


File: pm.info,  Node: Class/Phrasebook,  Next: Class/Phrasebook/SQL,  Prev: Class/ParmList,  Up: Module List

Implements the Phrasebook pattern
*********************************

NAME
====

   Class::Phrasebook - Implements the Phrasebook pattern

SYNOPSIS
========

     use Class::Phrasebook;
     my $pb = new Class::Phrasebook($log, "test.xml");
     $pb->load("NL"); # using Dutch as the language
     $phrase = $pb->get("ADDRESS",
     		     { street => "Chaim Levanon",
     		       number => 88,
     		       city   => "Tel Aviv" } );

DESCRIPTION
===========

   This class implements the Phrasebook pattern. It lets us create
dictionaries of phrases. Each phrase can be accessed by a unique key. Each
phrase may have placeholders. Group of phrases are kept in a dictionary.
The first dictionary is the default one - which means that it will always
be read. One of the dictionaries might be used to override the default
one. The phrases are kept in an XML document.

   The XML document type definition is as followed:

     <?xml version="1.0"?>
     <!DOCTYPE phrasebook [
     	       <!ELEMENT phrasebook (dictionary)*>
     	       <!ELEMENT dictionary (phrase)*>
                   <!ATTLIST dictionary name CDATA #REQUIRED>
                   <!ELEMENT phrase (#PCDATA)>
                   <!ATTLIST phrase name CDATA #REQUIRED>
     ]>

   Example for XML file:

     <?xml version="1.0"?>
     <!DOCTYPE phrasebook [
     	       <!ELEMENT phrasebook (dictionary)*>
     	       <!ELEMENT dictionary (phrase)*>
                   <!ATTLIST dictionary name CDATA #REQUIRED>
                   <!ELEMENT phrase (#PCDATA)>
                   <!ATTLIST phrase name CDATA #REQUIRED>
     ]>
     <phrasebook>
     <dictionary name="EN">

     <phrase name="HELLO_WORLD">
                Hello World!!!
     </phrase>

     <phrase name="THE_HOUR">
                The time now is $hour.
     </phrase>

     <phrase name="ADDITION">
                add $a and $b and you get $c
     </phrase>

     <!-- my name is the same in English Dutch and French. -->
     <phrase name="THE_AUTHOR">
                Rani Pinchuk
     </phrase>
     </dictionary>

     <dictionary name="FR">
     <phrase name="HELLO_WORLD">
                Bonjour le Monde!!!
     </phrase>

     <phrase name="THE_HOUR">
                Il est maintenant $hour.
     </phrase>

     <phrase name="ADDITION">
                $a + $b = $c
     </phrase>

     </dictionary>

     <dictionary name="NL">
     <phrase name="HELLO_WORLD">
                Hallo Werld!!!
     </phrase>

     <phrase name="THE_HOUR">
                Het is nu $hour.
     </phrase>

     <phrase name="ADDITION">
                $a + $b = $c
     </phrase>

     </dictionary>

     </phrasebook>

   Each phrase should have a unique name. Within the phrase text we can
place placeholders. When get method is called, those placeholders will be
replaced by their value.

CONSTRUCTOR
===========

new ( [ LOG ], FILEPATH )
     The constructor. FILEPATH can be the absolute path of the XML file.
     But it can be also just a name of the file, or relative path to the
     file. In that case, that file will be searched in the following
     places:    * The current directory.     * The directory ./lib in the
     current directory.     * The directory ../lib in the current
     directory.     * The directories that are in @INC.

     LOG is a Log object. If LOG is undef, NullLog object will be used.
     If it is provided, the class will use the Log facilities to log
     unusual events.  Returns the new object, or undef on failure.

METHODS
=======

load( DICTIONARY_NAME )
     Will load the phrases of certain dictionary from the file. If the
     dictionary that is requested is not the first one (in the XML file),
     the first dictionary will be loaded first, and then the requested
     dictionary phrases will be loaded.  That way, the first dictionary
     play the role of the default dictionary.

     The DICTIONARY_NAME data member will be set to the parameter that is
     sent to this method. Yet, if nothing is sent to the method, the
     method will use the value of the DICTIONARY_NAME data member to load
     the right dictionary.  If the data member is not defined as well, the
     default dictionary will be loaded.

     Returns 1 on success, 0 on failure.

get(KEY [, REFERENCE_TO_ANONYMOUS_HASH ]) Will return the phrase that fits to the KEY. If a reference to  anonymous has is sent, it will be used to define the parameters in the  phrase.
dictionary_name( DICTIONARY_NAME )
     Access method to the DICTIONARY_NAME data member. See load method
     above.

remove_new_lines ( BOOLEAN )
     Access method to the data member REMOVE_NEW_LINES flag. If this data
     member is true (1), then new lines will be removed from the phrase
     that a is returned by the method get.  Returns the value of the data
     member REMOVE_NEW_LINES flag.

ACCESS METHODS
==============

get_xml_path ( FILE )
     Will return the path of the xml file with that name. It will look for
     this file in the current directory, in ./lib ../lib and in all the
     directories in @INC.  If it is not found, NULL will be returned.

file_path( FILEPATH )
     Access method to the FILE_PATH data member. FILEPATH can be the
     absolute path of the XML file. But it can be also just a name of the
     file, or relative path to the file. In that case, that file will be
     searched in the following places:    * The current directory.     *
     The directory ./lib below the current directory.     * The directory
     ../lib below the current directory.     * The directories that are in
     @INC.

log( LOG )
     Access method to the LOG data member.

ENVIRONMENTS
============

PHRASEBOOK_DEBUG_PRINTS
     If this environment is set to "COLOR", the get method will print the
     phrases it gets, with some extra information in color screen output
     using ANSI escape sequences. If the environment is set to "HTML", the
     information will be printed in HTML format. If the environment is set
     to "TEXT" - the information will be printed as simple text. If the
     environment is not set, or empty - nothing will be printed. This
     feature comes to help debugging the phrases that we get from the
     object of this class.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `XML::Parser(3)' in this node, `Log::LogLite(3)' in this node,
`Log::NullLogLite(3)' in this node, The Phrasebook Pattern - Yonat Sharon
& Rani Pinchuk - PLoP2K -
http://jerry.cs.uiuc.edu/~plop/plop2k/proceedings/Pinchuk/Pinchuk.pdf


File: pm.info,  Node: Class/Phrasebook/SQL,  Next: Class/SelfMethods,  Prev: Class/Phrasebook,  Up: Module List

Implements the Phrasebook pattern for SQL statements.
*****************************************************

NAME
====

   Class::Phrasebook::SQL - Implements the Phrasebook pattern for SQL
statements.

SYNOPSIS
========

     use Class::Phrasebook::SQL;
     my $sql = new Class::Phrasebook::SQL($log, "test.xml");
     $sql->load("Pg");
     $statement = $sql->get("INSERT_INTO_CONFIG_ROW",
     		       { id => 88,
     			 parent => 77,
     			 level => 5 });

DESCRIPTION
===========

   This class inherits from Class::Phrasebook and let us manage all the SQL
code we have in a project, in one file. The is done by placing all the SQL
statements as phrases in the XML file of the Class::Phrasebook.  See
*Phrasebook* for details about that file format.

METHODS
=======

get(KEY [, REFERENCE_TO_ANONYMOUS_HASH ])
     Will return the SQL statement that fits to the KEY. If a reference to
     anonymous has is sent, it will be used to define the parameters in the
     SQL statement.

     For example, if the following statement is defined in the XML file:
     <statement name="INSERT_INTO_CONFIG_ROW">                insert into
     t_config (id, parent_id, level)                       values($id,
     $parent, $level)    </statement> We usually will call get method to
     get this statement in the following way:    $statement =
     $sql->get("INSERT_INTO_CONFIG_ROW",                           { id =>
     88,                             parent => 77,
        level => 5 });

     Special case are the SQL update instructions. Most of the time, when
     we call update, we would like to update only part of the columns in a
     row.  Yet, we usually prefer to avoid from writing all the possible
     update combinations. For example if we have the following update call:

          update t_account set
                                login = '$login',
                                description = '$description',
                                dates_id = $dates_id,
                                groups = $groups,
                                owners = $owners
                                            where id = $id

     We do not want to write special update for each case like:

          update t_account set
                                owners = $owners
                                            where id = $id

     or

          update t_account set
                                login = '$login',
                                owners = $owners
                                            where id = $id

     In order to solve this, the get method will delete the "set" lines of
     the update method where the were the parameter value is udefined.
     Because of that we should write the update statements were the pairs
     of <column name> = <parameter> are in separate lines from the rest of
     the statement. Note that the get method will also fix comma problems
     between the pairs (so if the last pair is deleted we will not have
     extra comma).  The method returns the SQL statement, or undef if
     there is no SQL statement for the sent KEY.

escaped_quote ( STRING )
     An access method to the data memeber ESCAPED_QUOTE. The default way
     to escape a quote is to have two quotes ("). This will work on
     Postgres and on MSQL.  Yet, if this default is not working with your
     database of choice, you can change it by seting the ESCAPE_QUOTE data
     member using this method.

use_is_null( BOOLEAN )
     Sometimes, when we have an argument in SQL statement, we will want to
     change the equal sign to 'is'. For example:

     		   select * from my_table where my_id = $id

     If $id is NULL, we sometimes want to have 'my_id is NULL'.  We can
     have that by sending to this method 1. This will promis that where
     ever we have the pattern '= NULL' it will become 'is NULL'. The
     default is not to use the 'is' (thus 0).

save_statements_file_path ( [ FILE_PATH ] )
     Access method to the SAVE_STATEMENTS_FILE_PATH data member. If this
     data member is set, for each call to the get method, the statement
     that is returned also will be appended to that file. This might be
     useful while debugging big projects - it will let the user have a
     full log of all the statemnets that were generated by the get method.

ENVIRONMENTS
============

PHRASEBOOK_SQL_DEBUG_PRINTS
     If this environment is set to "COLOR", the get method will print the
     statements it gets, with some extra information in color screen output
     using ANSI escape sequences. If the environment is set to "HTML", the
     information will be printed in HTML format. If the environment is set
     to "TEXT" - the information will be printed as simple text. If the
     environment is not set, or empty - nothing will be printed. This
     feature comes to help debugging the SQL statements that we get from
     the object of this class.

PHRASEBOOK_SQL_SAVE_STATEMENTS_FILE_PATH
     Another way to set the SAVE_STATEMENTS_FILE_PATH data member is by
     setting this environment variable.

AUTHOR
======

   Rani Pinchuk, rani@cpan.org

COPYRIGHT
=========

   Copyright (c) 2001 EM-TECH (www.em-tech.net) & Rani Pinchuk.  All
rights reserved.  This package is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

SEE ALSO
========

   `XML::Parser(3)' in this node, `Class::Phrasebook(3)' in this node,
`Log::LogLite(3)' in this node, `Log::NullLogLite(3)' in this node


File: pm.info,  Node: Class/SelfMethods,  Next: Class/Singleton,  Prev: Class/Phrasebook/SQL,  Up: Module List

a Module for supporting instance-defined methods
************************************************

NAME
====

   Class::SelfMethods - a Module for supporting instance-defined methods

SYNOPSIS
========

     use Class::SelfMethods;

     package MyClass;
     @ISA = qw(Class::SelfMethods);
     use strict;

     sub _friendly {
       my $self = shift;
       return $self->name;
     }

     package main;
     no strict;

     my $foo = MyClass->new( name => 'foo' );
     my $bar = MyClass->new( name => 'bar', friendly => 'Bar');
     my $bas = MyClass->new( name => 'bas',
                             friendly => sub {
                               my $self = shift;
                               return ucfirst($self->_friendly);
                             }
                           );

     print $foo->friendly, "\n";
     print $bar->friendly, "\n";
     print $bas->friendly, "\n";

     $bas->friendly_SET('a reset friendly');
     print $bas->friendly, "\n";

     $bas->friendly_SET( sub { my $self = shift; return uc($self->_friendly) });
     print $bas->friendly, "\n";

     $bas->friendly_CLEAR;
     print $bas->friendly, "\n";

DESCRIPTION
===========

   `Class::SelfMethods' merges some features of other Object Oriented
languages to build a system for implementing more flexible objects than is
provided by default in Perl.

   The core features I was looking for when I wrote `Class::SelfMethods'
were:

Class-based inheritance hierarchy
     I wanted to retain Perl's normal class-based inheritance hierarchy
     rather than to write (or use) a completely prototype based system.
     If you are looking for a purely prototype based system, see Sean M.
     Burke's `Class::Classless'.  My reasoning on this is that it is
     easier in file based languages (as opposed to world based languages
     like Self) to code class based inheritance hierarchies (which are
     largely static) than to code object based inheritance hierarchies
     (since objects in such languages have a dynamicism that is not
     granted to classes).

Instance-defined method overriding
     I wanted instances to be able to override their class-defined
     methods.  In the example above, the `$bas' object has its own
     `friendly' method.  Instance-defined methods are passed the exact
     same parameter list as class-defined methods.

Subroutine/Attribute equivalence
     Borrowing from Self, I wanted to be able to treat methods and
     attributes similarly.  For instance, in the above example the `$bar'
     object has an attribute `friendly', whereas the `$bas' object has a
     method `friendly', and the `$foo' object uses the class-defined
     method.  The calling syntax is independent of the implementation.
     Parameters can even be passed in the method call and they will simply
     be ignored if the method is implemented by a simple attribute

   In addition to those core features, I (and Damian) had a wish list of
additional features:

Simple syntax
     I wanted the system to be reasonable easy to use for both
     implementers of classes and users of objects.  Simple syntax for
     users is more important than simple syntax for implementers.

Full support for SUPER type concepts
     I wanted instance-defined methods to be able to call the
     class-defined methods they replace.

Support for calling methods at instantiation time
     In some circumstances, rather than deal with multiple inheritance it
     is easier to have a class-defined object method that sets up the
     various instance-defined methods for a given object.  To support
     this, the new method allows deferred method calls to be passed in as
     parameters.

Modifying objects post-instantiation
     I originally had no need for modifying objects post-instantiation,
     but Damian Conway thought it would be a Good Thing (TM) to support.
     Being so very good at these sorts of thing, he instantly came up with
     a good general syntax to support such.  Method calls that end in a
     `_SET' result in the first parameter being assigned to the
     attribute/method.  I noticed one remaining hole and added support for
     `_CLEAR'.

HOW TO
======

Write A Class
-------------

   Your class should inherit from `Class::SelfMethods'.  The class-defined
instance methods should be *defined with* a leading underscore and should
be *called without* a leading underscore.  Don't do anything silly like
writing methods whose proper names have a leading underscore and whose
definitions have two leading underscores - that's just asking for trouble.

   Do not, of course, make use of attributes that have leading underscores
- that's also just asking for trouble.  Also, do not access attributes
directly (i.e. `$self->{foo}').  That will prevent people who use your
class from substituting a method for an attribute.  Instead, always read
attributes by making the corresponding method call (`$self->foo').

   If you need to call `SUPER::methodname', call `SUPER::_methodname'.

Create An Instance
------------------

   The default new method uses named parameters.  Unless you are
certifiable, you will too.  To specify attributes, simply use the syntax
`name => 'value'' and to specify a method use `name => sub { my $self =
shift; . . . }'.  Note that methods and attributes are interchangeable.

Modify An Instance
------------------

   Method calls that end in a `_SET' will result in their first parameter
being assigned to the appropriate attribute/method.  For instance, in the
SYNOPSIS I use `$foo->friendly_SET' to specify both a value and a method
for `friendly'.  Method calls that end in a `_CLEAR' will delete that
attribute/method from the object.  The can method will behave just like
UNIVERSAL::can - it returns a code reference that will interoperate with
the associated object properly using the `$obj->$coderef()' syntax.  For
examples of usage, see test.pl.

Installation instructions
-------------------------

   Standard module installation procedure.

INTERNALS
=========

can
---

   This implementation of can is the heart of the system.  By making can
responsible for almost everything relating to accessing the objects, the
code for deciding how to respond to the various situtations is kept in one
place.

   In order to get major speed improvements (a factor of 2 to 3 for
attribute retrieval and method calls), extensive symbol table manipulation
was used to build methods on the fly that react appropriately.

   The three types of methods are `_SET' methods, `_CLEAR' methods, and
"normal" methods.  The first two are fairly straight forward as far as
implementation goes.  First UNIVERSAL::can is called to determine whether
an appropriate entry has been made in the package symbol table.  If not,
an anonymous subroutine (actually, a closure in this case because `$func'
is a lexically scoped variable defined outside the anonymous subroutine
and referenced from within) is created and assigned into the package
symbol table.  In either case, a reference to the appropriate closure is
returned (normal can behavior is to return a reference to the code or
undef if the method call is not legal).

   The "normal" methods are somewhat trickier.  The outer if statement
exists to ensure that can returns undef for illegal method calls (remember
that there may be situations where `$self->can($func)' should return false
even though `UNIVERSAL::can($self, $func)' returns true). It then checks
whether an appropriate entry has been made in the package symbol table.  If
not, it builds a closure that will do the trick.  Remember that the
closure could get called on an object that is in any of the four possible
states - attribute, instance method, inherited method, or illegal.  The
closure includes the logic to test for instance methods and attributes,
but if neither are present it will make the call to `_method' regardless
of whether or not there is an inherited method with the proper name.  It
relies on AUTOLOAD to properly deal with unhandled `_method' calls.

AUTOLOAD
--------

   AUTOLOAD gets called the first time a given method call is made.  It
first strips off the package name from the function call to extract the
actual function name.  It then checks to see if the function name starts
with an underscore.  If it does, it's a failed call from the "normal"
method closure, so AUTOLOAD calls croak to die with the appropriate error
message.  Notice that the underscore has been stripped off, so it will die
failing to find method.

   AUTOLOAD then calls can, which will return a reference to the
appropriate CODE entity if the method call is supported.  At the same
time, can puts an entry into the symbol table for `Class::SelfMethods' to
support future calls to that method.  AUTOLOAD jumps to that CODE entity
if a valid entity was return.  Otherwise, execution continues on to
another croak call.

new
---

   The new method supplied in `Class::SelfMethods' provides one
interesting twist on an otherwise standard named parameters constructor.
It strips out any passed parameters that have leading underscores and
stores them away.  It then creates the hash ref from the remaining
parameters and blesses it appropriately.  Finally, it takes the stored
parameters that have leading underscores and makes the matching method
calls - the key is used for the method name and the value is dereferenced
to an array and passed as parameters.

AUTHOR
======

   Toby Everett, teverett@alascom.att.com

CREDITS
=======

Damian Conway, damian@cs.monash.edu.au
     Responsible for accessor methods, module name, constructive criticism
     and moral support.  After I responded to Sean's suggestion of
     implementing a can method, Damian completely rewrote my first attempt
     by routing everything through can. He also was the first to point out
     direct symbol table manipulation by implementing it for the `_SET'
     and `_CLEAR' methods.  I rebutted his routing everything through can
     by doing performance testing.  He agreed that the performance issues
     were a problem, but suggested retaining the direct symbol table for
     the accessor methods.  It was then that the lightbulb went off and I
     realized that a properly written closure could be used for the normal
     method calls. Damian's criticisms kept me on track and from making a
     fool of myself, and the result is some very fast (and I hope safe:)
     code.

     I first started writing to Damian as a result of an excellent book he
     wrote, Object Oriented Perl.  I highly recommend it - get it, read it.

Sean M. Burke, sburke@netadventure.net
     Suggested implementing a can method.  Sean was/is responsible for
     `Class::Classless'.  If you need a full-featured purely prototype
     based object system, check it out.


