NAME

XML::Object - Methodical XML Configuration

SYNOPSIS

XML

    <config>
	<run name="John Doe">
	    <port>4321</port>
	    <user>bar</user>
	</run>
	<foo>
	    <port>1234</port>
	    <bar>
		<baz>Luhrmann</baz>
	    </bar>
	    <list>alpha</list>
	    <list>
		<beta>gamma</beta>
	    </list>
	    <list>vlissides</list>
	    <email>foo@bar.com</email>
	    <address>1 Foo Street, Bar FB1 1FB</address>
	</foo>
	<user>foo</user>
    </config>

XML::Simple

    {
	run => {
	    name    => 'John Doe',
	    port    => '4321',
	    user    => 'bar'
	},
	foo => {
	    port    => '1234',
	    bar	    => {
		baz => 'Luhrmann'
	    },
	    list => [
		'alpha',
		{
		    'beta' => 'gamma'
		},
		'vlissides'
	    ],
	    email   => 'foo@bar.com',
	    address => '1 Foo Street, Bar FB1 1FB'
	},
	user => 'foo'
    }

main.pl

    use Foo;

    # call from a subroutine to demonstrate caller_test() / caller_demand()
    sub run { 
	my $foo = Foo->new($config_file, %optional_xml_simple_options);
	$foo->foo();
    }

    run();

Foo.pm

    package Foo;

    use base qw(XML::Object);
    # package can now configure itself via XML

    # optional constructor
    sub new {
	my $class = shift;
	my $self = $class->SUPER(@_);

	# ...
    }

    sub foo {
	my $self = shift;

	# optional: test() returns undef if the value isn't found
	# equivalent to $self->config()->{foo}->{port} 
	my $port = $self->test('port') || 8080;

	# compulsory: demand() throws an exception if the value isn't found
	# equivalent to $self->config()->{foo}->{email} 
	my $email = $self->demand('email');

	# arbitrarily deep path expressions
	# equivalent to $self->config()->{foo}->{list}->[1]->{beta} 
	my $leaf = $self->demand('list', 1, 'beta');

	# provide an explicit key: $self->config()->{user} 
	my $user = $self->key_test('user');

	# use the name of the function that called this function as the root
	# equivalent to $self->config()->{run}->{name}
	my $name = $self->caller_demand('name');

	# equivalent to $self->key_demand('foo')  i.e. $self->config()->{foo}
	my $foo = $self->demand();

	# supply your own configuration HASH or ARRAY ref
	my $alpha = $self->key_test($array_or_hash_ref, 'alpha');
	my $beta = $self->key_demand($array_or_hash_ref, 'beta');
    }

DESCRIPTION

XML::Object allows easy (XML) configuration of a Perl script/module by associating methods with elements. Because each method has its own configuration 'namespace', the structure of the XML reflects that of the object and vice-versa. This partitioning leads to a simple and intuitive organisation of the configuration space.

XML::Object::DBI adds a database accessor (get) and mutator (set) to the mix. These shield the user from DBI housekeeping while freeing them to manage the SQL in an intuitive and flexible way.

METHODS

test

usage

    sub example {
	my $self = shift;

	# i.e. $self->key_test('example', 'port');
	my $optional1 = $self->test('port') || 8080;

	    # or 

	# i.e. $self->key_test($hash_or_array_ref, 'example', 'port');
	my $optional2 = $self->test($hash_or_array_ref, 'port');
    }

summary

test() looks up a scalar, ARRAY ref or HASH ref using the name of the current subroutine and any supplied arguments as the root (i.e. first HASH key or ARRAY index) of the path into the configuration HASH or ARRAY ref.

Numbers and strings in the path are interpreted according to the context discovered during the course of the lookup. Thus in the following example:

    sub foo {
	my $self = shift;
	my $test = $self->test('list', 1, 'beta');
    }

That path is first translated into the equivalent of:

$self->key_test('foo', 'list', 1, 'beta');

Which in turn becomes:

$self->config()->{foo}->{list}->[1]->{beta} 

test(), demand(), caller_test(), caller_demand(), key_test() and key_demand() can be passed a HASH or ARRAY ref as the first argument. The lookup is then performed against this structure rather than the object's configuration HASH/ARRAY ref.

e.g.

my $login = $self->demand('login'); # grab the login HASH
my $user = $self->key_demand($login, 'username'); # compulsory username
my $password = $self->key_test($login, 'password'); # optional password

demand

usage

    sub example {
	my $self = shift;

	# i.e. $self->key_demand('example', 'user');
	my $compulsory1 = $self->demand('user');

	    # or

	# i.e. $self->key_demand($array_or_hash_ref, 'example', 'user');
	my $compulsory2 = $self->demand($array_or_hash_ref, 'user');
    }

summary

demand() works the same as test(), but raises an exception if the specified value is not defined or the path is invalid.

caller_test

usage

    sub run {
	my $self = shift;
	$self->example();
    }

    sub example {
	my $self = shift;

	# i.e. $self->key_test('run', 'port');
	my $optional1 = $self->caller_test('port') || 8080;

	    # or 

	# i.e. $self->key_test($array_or_hash_ref, 'run', 'port');
	my $optional2 = $self->caller_test($array_or_hash_ref, 'port') || 8080;
    }

summary

caller_test() uses the name of the subroutine that called the current subroutine as the root of the path. Otherwise its use is the same as test().

caller_demand

usage

    sub run {
	my $self = shift;
	$self->example();
    }

    sub example {
	my $self = shift;

	# i.e. $self->key_demand('run', 'user');
	my $compulsory1 = $self->caller_demand('user');

	    # or

	# i.e. $self->key_demand($array_or_hash_ref, 'run', 'user');
	my $compulsory2 = $self->caller_demand($array_or_hash_ref, 'user');
    }

summary

caller_demand() uses the name of the subroutine that called the current subroutine as the root of the path. Otherwise its use is the same as demand().

key_test

usage

    sub example {
	my $self = shift;

	my $optional = $self->key_test('port') || 8080;
	    # or
	my $optional = $self->key_test($array_or_hash_ref, 'port') || 8080;
    }

summary

key_test() uses only the explicitly specified key(s) to index into the default or supplied configuration ARRAY or HASH ref. The other flavours of test() are implemented as wrappers of key_test().

key_demand

usage

    sub example {
	my $self = shift;
	my $compulsory1 = $self->key_demand('user');
	    # or
	my $compulsory2 = $self->key_demand($array_or_hash_ref, 'user');
    }

summary

key_demand() uses only the explicitly specified key(s) to index into the default or supplied configuration ARRAY or HASH ref. The other flavours of demand() are implemented as wrappers of key_demand().

configure

usage

    my $path = $self->configure();

	# or 

    my ($path, $xml_simple_options) = $self->configure();

	# or 

    $self->configure($path, %optional_xml_simple_args);

summary

When called with no arguments configure() returns a) the path to the configuration file in scalar context, or b) the path and a reference to the (possibly empty) HASH of XML::Simple::XMLin() options in list context.

When called with a path argument and an optional HASH of arguments to be supplied to XML::Simple's XMLin(), a new configuration HASH or ARRAY ref is initialized in the object and returned.

config

usage

    my $config = $self->config();

	# or 

    $self->config($array_or_hash_ref);

summary

When called with no arguments config() returns the configuration HASH ref or ARRAY ref associated with the object.

When called with an argument that value is assigned as the object's new configuration.

parent

usage

my $caller = $self->parent();

summary

Returns the name (minus namespace) of the subroutine that called the current subroutine. Throws an exception unless that value is defined.

grandparent

usage

my $caller_caller = $self->grandparent();

summary

Returns the name (minus namespace) of the subroutine that called the subroutine that called the current subroutine. Throws an exception unless that value is defined.

EXCEPTIONS

XOE

Superclass for all XML::Object Exceptions.

XOE::BadConfig

Thrown if an attempt is made to assign an invalid (i.e. nonexistent or zero-length) configuration file.

XOE::BadGrandparent

Thrown if a caller_get* or caller_set* method is invoked in a context in which the call stack isn't deep enough for the grandparent of the caller_* method to be identified.

XOE::BadLookup

Thrown if a demand() fails either a) by being resolved to a value that is undefined or b) if the path is not valid within the configuration ARRAY or HASH ref.

XOE::BadParent

Thrown if a get* or set* method is invoked in a context in which the call stack isn't deep enough for the parent of the get* or set* method to be identified.

XOE::BadXML

Thrown if an error occurs during XML::Simple's XMLin() routine, which turns the specified XML into a Perl data structure.

EXPORT

None by default.

SEE ALSO

XML::Object::DBI, XML::Simple

AUTHOR

chocolateboy <chocolate.boy@email.com>

COPYRIGHT AND LICENSE

Copyright 2003 by chocolateboy

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