package Data_holder;
=head CONSTRUCTOR
Nothing terribly exciting here. All we do is bless a
hashref, embed a data hash, and store two hashes that map
attribute names to the names of the methods that will handle
them.
=cut
sub new {
my $O = bless {}, shift;
$O->{'data'} = {};
$O->{'get-funcs'} = {
'key-1' => 'get_normal',
'key-2' => 'get_synthetic',
};
$O->{'set-funcs'} = {
'key-1' => 'set_normal',
'key-2' => 'set_synthetic',
};
return ($O);
}
=head1 DISPATCH FUNCTIONS
=over 4
=item get (list) : hash
This is the inspection routine. It takes a list of
attribute names as input, and returns a hash of named
values as output. It does its job by calling functions
identified in {'get-funcs'}.
=cut
sub get {
my ($O, @keys) = @_;
my $result = {};
for my $k (@keys) {
my $func = $O->{'get-funcs'}->{ $k } || 'get_error';
$result->{ $k } = $O->$func ( $k );
}
return ($result);
}
=item set (hash) : hash
This is the storage function. It takes a hash of named
values as input, and returns a hash of result codes as
output. It does its job by calling functions identified
in {'set-funcs'}.
=cut
sub set {
my ($O, $args) = @_;
my $result = {};
for my $k (keys %$args) {
my $func = $O->{'set-funcs'}->{ $k } || 'set_error';
$result->{ $k } = $O->$func ( $k, $args->{ $k } );
}
return $result;
}
=back
=head1 INSPECTION METHODS
These are the functions that do the actual work of getting
values. They're called by get() when it finds their names
in {'get-funcs'}.
=over 4
=item get_normal (key) : value
This routine simply pulls the named value from the
emedded hash.
=cut
sub get_normal {
my ($O, $key) = @_;
return ($O->{'data'}->{ $key });
}
=item get_synthetic (key) : value
This routine is a little more interesting. It
calculates the return value from some other value or
combination of values in the embedded data hash. In
this case, we'll calculate the farenheit value of a
stored centigrade temperature.
This is also just an example. In a real version of this
class, you'd have a different function for every value
you wanted to calculate.
=cut
sub get_synthetic {
my ($O, $key) = @_;
my $result = 32 + (1.8 * $O->{'data'}->{'temperature'});
return ($result);
}
=back
=head1 STORAGE METHODS
These are the functions that do the actual work of setting
values. They're called by set() when it finds their names
in {'set-funcs'}.
=over 4
=item set_normal (key, value) : result
This is the basic storage routine. It drops the value
into the embedded data hash under the assigned key. It
also returns a success code since there's no way that
operation can fail.
=cut
sub set_normal {
my ($O, $key, $val) = @_;
$O->{'data'}->{ $key } = $val;
return ('SUCCESS');
}
=item set_synthetic (key, value) : result
Like get_synthetic(), this is a sample routine. Here we
store the centigrade value of a temperature entered in
farenheit.
=cut
sub set_synthetic {
my ($O, $key, $value) = @_;
$O->{'data'}->{'temperature'} = ($value / 1.8) - 32;
return ('SUCCESS');
}
=back
=head1 ERROR ROUTINES
These are the catch-all routines. They handle keys that
don't have set() or get() functions defined in the
lookup tables.
In theory, you could use these routines to replace the
get_normal() and set_normal() operations, but I really don't
like that idea. It makes typos *way* too powerful for my
taste. I prefer to define my interfaces explicitly.
=over 4
=cut
sub get_error {
my ($O, $key) = @_;
return (
"FAILURE - "
. "I don't know how to locate the value for '$key'."
);
}
sub set_error {
my ($O, $key, $val) = @_;
return (
"FAILURE - "
. "I don't know how to set '$key' to '$value'."
);
}
####
sub set_normal {
my ($O, $key, $val) = @_;
my $func = $O->{'validate-funcs'}->{ $key };
my $result = $O->$func ($val);
if ($result eq 'SUCCESS') {
$O->{'data'}->{ $key } = $val;
}
return ($result);
}
####
sub new {
{...}
$O->{'synonyms'} = {
'rm' => 'REQUEST_METHOD',
'q' => 'QUERY_STRING',
{...}
};
{...}
}
sub get {
my ($O, @keys) = @_;
my $result = {};
for my $k (@keys) {
my $real_key = $O->{'synonyms'}->{ $k } || $k;
my $func = $O->{'get-funcs'}->{ $real_key }
|| 'get_error'
;
$result->{ $k } = $O->$func ($real_key);
}
return ($result);
}
####
$O->$func ($key);
####
package Command;
sub new {
return (bless {}, shift);
}
sub execute {
}
package Get_normal;
@ISA = qw( Command );
sub execute {
my ($O, $target, $key) = @_;
$target->get_normal ($key);
return;
}
package Data_holder;
sub new {
{...}
my $g = new Get_normal;
$O->{'get-funcs'} = {
'key-1' => $g,
{...}
}
{...}
}
sub get {
{...}
my $cmd = $O->{'get-funcs'}->{ $k }
|| $O->{'get-funcs'}->{'get_error'}
;
$result->{ $k } = $cmd->execute ( $k );
{...}
}