![]() |
![]() |
package XML::Schema::MyModule; use base qw( XML::Schema::Base ); use vars qw( $ERROR @MANDATORY %OPTIONAL ); @MANDATORY = qw( id ); %OPTIONAL = ( msg => 'Hello World' ); sub init { my ($self, $config) = @_; # search inheritance tree for mandatory/optional params $self->init_mandopt($config) || return; return $self; } package main; my $module = XML::Schema::MyModule->new( id => 12345 ) || die $XML::Schema::MyModule::ERROR;
This module implements a base class from which all other XML::Schema::* modules are subclassed. Unless you're hacking on the internals of the XML::Schema::* modules then you probably don't need to worry too much about what's going on in here.
It implements a new()
constructor method for
instantiating objects which works in conjunction with an
init()
which performs per-object initialisation.
Splitting this object creation process into two methods makes
subclassing much easier.
It also implements a general purpose error()
method which objects can use to report error conditions and
callers can use to query those errors.
Various other useful "private" methods are defined for the base class and in some cases, subclasses to use for debugging, examining package variables, and other miscellaneous tasks.
The throw()
method, when called by an object
without specifying an exception type, e.g.
$myobject->throw('attempt to fit round peg in square hole');
$ETYPE
package variable
in the object's package and if defined, will use that
value as the default error type.
Internal value used by the _text_snippet()
method to define the default length to truncate text to. Set
to 16 by default.
Controls the depth to which the _inspect()
debugging method recurses into the depths of nested data
structures. Set to 3 by default.
new( \%config )
new( key => value, key => value, ... )
General purpose constructor method which can be used to instantiate new objects of classes derived from XML::Schema::Base.
The method expects a hash array of configuration items either
passed directly by reference or as list of key =>
value
pairs which are automatically folded into a hash
reference. A new object is constructed from a blessed hash
and the init()
method is called, passing the
configuration hash as an argument.
package XML::Schema::MyModule; use base qw( XML::Schema::Base ); use vars qw( $ERROR ); package main; my $obj1 = XML::Schema::MyModule->new({ pi => 3.14, e => 2.718 }); my $obj2 = XML::Schema::MyModule->new( pi => 3.14, e => 2.718 );
Called by the new()
constructor to perform
any per-object initialisation. A reference to a hash array of
configuration parameters is passed as an argument. The method
should return $self on success or undef on failure (e.g. by
calling $self->error()
).
sub init { my ($self, $config) = @_; $self->{ _LIKES } = $config->{ likes } || return $self->error("no 'likes' parameter specified") return $self; }
Optional initialisation method utilised by some derived
modules which examines the @MANDATOY
and
@OPTIONAL
or
%OPTIONAL
package variables in all of the
object's superclasses to construct a full list of mandatory
and optional arguments for the object.
The method then examines both lists copying corresponding
values from the $config
into
$self
. Any variables named in the
mandatory list must be defined or an error will be raised
and undef returned.
sub init { my ($self, $config) = @_; # search inheritance tree for mandatory/optional params $self->init_mandopt($config) || return; return $self; }
Can be called as a class or object method to get or set the relevant error variable. Returns the current value of the error variables when called without arguments, or undef when called with argument(s) which are used to set the error variable (multiple arguments are concatenated).
# class method to set $XML::Schema::MyModule::ERROR XML::Schema::MyModule->error('Failed to have cake and eat it'); # class method to retrieve $XML::Schema::MyModule::ERROR warn XML::Schema::MyModule->error(); # object method to set $myobj->{ _ERROR } $myobj->error('Stone throwing detected in glass house'); # object method to get $myobj->{ _ERROR } warn $myobj->error();
error_value( $item, $got, @legal )
Generates a formatted error message and passes it to the
error()
method. This method is used to
report an illegal value specified for a parameter. The first
argument indicates the name of the item, the second specifies
the illegal value received and the remaining arguments give
legal alternatives. A call such as:
is then equivalent to:$myobj->error_value('doodah', 'badval', 'foo', 'bar', 'baz');
$myobj->error("doodah must be 'foo', 'bar' or 'baz' (not: 'badval')");
throw( $exception )
throw( $error )
throw( $type, $info )
Called to throw an error as an XML::Schema::Exception object using the error message passed as the first argument as the information field for the exception. The error type is defined in the $ETYPE package variable in the derived class or defaults to the value of $ETYPE in this base class package (the string 'undef', by default).
package XML::Schema::MyModule; use base qw( XML::Schema::Base ); use vars qw( $ETYPE ); $ETYPE = 'MyModule'; package main; $myobj = XML::Schema::MyModule->new(); $myobj->throw('An error'); # throws "[MyModule] An error"
Alternately, the method can be called with two explicit arguments to denote the type and info fields.
$myobj->throw('Cake', 'Let them eat it!'); # throws "[Cake] Let them eat it!"
factory( $factory )
factory( )
Various objects need to create instances of other objects at
various time. To avoid hard-coding loads of package names
across numerous different files, the objects instead delegate
to a factory object to perform this task in a well-defined and
extensible manner. Objects can be passed a
factory
argument with their constructor which can
contain the name of an object class or reference to an object
which should be used as a factory by that object. This method
can also be called on a previously instantiated object to set
or update the value for its factory.
When called without arguments, the method returns the current internal _FACTORY value or if undefined, the class or object reference defined in the $XML::Schema::FACTORY .
These methods are deemed "private" (or more accurately, "protected") and are intended for the use of classes derived from XML::Schema::Base.
Private Methods:
_baseargs( $name, $name, ... )
This method walks up the inheritance tree collecting various package variables along the way and collating them for the derived object class. Variable names in which the caller is interested should be passed as arguments. A reference to a list is returned which contains further references to lists and/or hash arrays, depending on the variable type.
sub init { my ($self, $config) = @_; my $baseargs = $self->_baseargs(qw( @MANDATORY %OPTIONAL )); my ($mandatory, $optional) = @$baseargs; ... return $self; }
For example, consider the following inheritance tree:
package XML::Schema::Test::Foo; use base qw( XML::Schema::Base ); use vars qw( @MANDATORY %OPTIONAL ); @MANDATORY = qw( one two ); %OPTIONAL = ( foo => 'default foo' ); package XML::Schema::Test::Bar; use base qw( XML::Schema::Base ); use vars qw( @MANDATORY %OPTIONAL ); @MANDATORY = qw( three four ); %OPTIONAL = ( bar => 'default bar' ); package XML::Schema::Test::Baz; use base qw( XML::Schema::Test::Foo XML::Schema::Test::Bar ); use vars qw( @MANDATORY %OPTIONAL ); @MANDATORY = qw( five six ); %OPTIONAL = ( baz => 'default baz' );
Now let's call the _baseargs() method against these different packages and see what they return.
my @names = qw( @MANDATORY %OPTIONAL ); XML::Schema::Test::Foo->_baseargs(@names); # returns: # [ # [ 'one', 'two' ] # { foo => 'default foo' } # ] XML::Schema::Test::Bar->_baseargs(@names); # returns: # [ # [ 'three', 'four' ] # { bar => 'default bar' } # ] XML::Schema::Test::Baz->_baseargs(@names); # returns: # [ # [ 'one', 'two', 'three', 'four' ] # { foo => 'default foo' # bar => 'default bar' # baz => 'default baz' # } # ]
Note that package variables specified as hash arrays can also be specified as lists. In this case, the list is assumed to represent the hash keys which all have empty (but defined) values.
@OPTIONAL = qw( foo bar ); # equivalent to: %OPTIONAL = ( foo => '', bar => '' );
_mandatory( \@names, \%config )
This method examines the $config hash array for values specified by name in the $names list and copies them to the $self object. All items are deemed mandatory and the method will raise an error and return undef if any item is not defined.
sub init { my ($self, $config) = @_; my $baseargs = $self->_baseargs(qw( @MANDATORY )); return $self->_mandatory($baseargs->[0], $config); }
_optional( \%names, \%config )
Like _mandatory()
, this method examines the
$config hash array for values specified as keys in the
$names hash and copies them to the $self object. The values
in the $names hash are used as defaults for items which are
not defined in $config. If the default value contains a
CODE reference then the subroutine will be called. The
$names item may also be specified as a reference to a list
in which case all default values are set to the empty
string, ''.
sub init { my ($self, $config) = @_; my $baseargs = $self->_baseargs(qw( %OPTIONAL )); return $self->_optional($baseargs->[0], $config); }
Similar to _mandatory()
and
_optional()
above, this method sets named
values but in this case from positional arguments. The
expected names of values are specified by reference to a
list as the first argument and the list of candidate values
is passed by reference as the second. An error is raised
and undef returned if any value is undefined.
Debug Methods:sub new { my ($class, @args) = @_; my $baseargs = $class->_baseargs('@ARGUMENTS'); my $self = bless { _ERROR => '', }, $class; return $self->_arguments($baseargs->[0], \@args) || $class->error($self->error()); }
DEBUG( $msg, $msg, ... )
Simple debugging method which prints all arguments to
STDERR.
$myobj->DEBUG("The cat sat on the mat\n");
TRACE( @args )
More funky debugging method which generates a trace message
showing various potentially useful items, depending on the
value defined in the objects _DEBUG
value or the
$DEBUG
package variables in the object's class.
The higher the value (currently 0-4) the more detail is
generated.
$myobj->TRACE("The ", $cat, " sat on the ", $mat);
ID()
Returns a string representing an identifier for the object
for debugging purposes. By default, the value of the
$ETYPE
variable in the object's package
is return. Subclasses will most likely redefine this
method to return some more meaningful value.
_inspect( $something )
_inspect( $something, $level )
Attempts to Do The Right Thing to print a meaningful
representation of the $something
passed as an
argument. Will recurse into $something
's
structure while $level
is less than
$INSPECT_LEVEL
.
_text_snippet( $text )
_text_snippet( $text, $length )
Returns $text
truncated to (at most)
$length
characters, or the current value
of $SNIPPET
if $length
is unspecified. Strings that are truncated are returned
with '...' appended.