Modules Index

XML Schema Home

# XML::Schema::Base

This module implements a base class from which all other XML::Schema::* modules are subclassed.

## Table of Contents

Synopsis |  |  |
Description |  |  |
Package Variables | : | $ETYPE, $SNIPPET, $INSPECT_LEVEL |
Methods | : | new(), init(), init_mandopt(), error(), error_value(), throw(), factory() |
Private Methods | : | _baseargs(), _mandatory(), _optional(), _arguments(), DEBUG(), TRACE(), ID(), _inspect(), _text_snippet() |

## Synopsis

    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;

## Description

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.

## Package Variables

- $ETYPE

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

  will look for the `$ETYPE` package variable in the object's package and if defined, will use that value as the default error type.
- $SNIPPET

  Internal value used by the `_text_snippet()` method to define the default length to truncate text to. Set to 16 by default.

- $INSPECT_LEVEL

  Controls the depth to which the `_inspect()` debugging method recurses into the depths of nested data structures. Set to 3 by default.

## Methods

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

- init( \%config )

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

- init_mandopt( \%config )

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

- error( $msg, $msg, ... )

  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:

      $myobj->error_value('doodah', 'badval', 'foo', 'bar', 'baz');

  is then equivalent to:

      $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 .

## Private Methods

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

- _arguments( \@names, \@args )

  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.

      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 Methods:

- 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.

Perl XML::Schema Documentation