NAME
    Apache::AxKit::Language::XSP::ObjectTaglib - Helper for OO Taglibs

SYNOPSIS
        package MyTaglib;
        use strict;
        use warnings;
        use base 'Apache::AxKit::Language::XSP::ObjectTaglib';
        use vars qw(@specification);

        @specification = (
            ...
        );

DESCRIPTION
    This is an AxKit tag library helper for easily wrapping object-oriented
    classes into XSP tags. The interface to the class is through a
    specification which your taglib provides as a package variable. You may
    wrap single or multiple classes within the same taglib, iterate over
    several objects, and call methods on a given object.

    Here is a sample specification:

        @specification = (
          {
            tag     => 'name',
            context => 'resources',
            target  => 'resource'
          }, {
            tag      => 'resources',
            target   => 'course',
            type     => 'loop',
            iterator => 'resource'
          }, {
            tag   => 'courses',
            type  => 'special',
            start => \&start_courses,
            end   => \&end_courses
          }, {
            tag    => 'name',
            target => 'course'
          }, {
            tag    => 'code',
            target => 'course'
          }, {
            tag    => 'description',
            target => 'course',
            type   => 'as_xml'
          }, {
            tag    => 'summary',
            target => 'course',
            type   => 'as_xml'
          }, {
            tag      => 'presentations',
            target   => 'course',
            type     => 'loop',
            iterator => 'presentation'
          }, {
            tag    => 'size',
            key    => 'calculateSize',
            target => 'presentation',
            notnull => 1
          }, {
            tag      => 'prerequisites',
            target   => 'course',
            type     => 'loop',
            iterator => 'course'
          }
        );

    This is the specification used in the sample
    "AxKit::XSP::ObjectTaglib::Demo" Taglib so all variable names used in
    the examples below start with "_xsp_axkit_xsp_objecttaglib_demo_".
    Here's what this means:

          {
            tag     => 'name',
            context => 'resources',
            target  => 'resource'
          }, {

    Define a tag called "name" which occurs inside of another tag called
    "resources". (We'll define a top-level "name" tag for "courses" later,
    so this context-sensitive override has to come first.) When this tag is
    seen, the method "name" will be called on the variable
    @_xsp_axkit_xsp_objecttaglib_demo_resource.

          }, {
            tag      => 'resources',
            target   => 'course',
            type     => 'loop',
            iterator => 'resource'
          }, {

    Define a tag called "resources" that will loop through each "resource"
    returned by the method "resources" on the "course" object. When combined
    with the first defined tag, the code generated looks something like
    this:

        for $_xsp_axkit_xsp_objecttaglib_demo_resource
          ($_xsp_axkit_xsp_objecttaglib_demo_course->resources) {
          $_xsp_axkit_xsp_objecttaglib_demo_course->name;
        };

    Now, on the main looping tag "courses".

          }, {
            tag   => 'courses',
            type  => 'special',
            start => \&start_courses,
            end   => \&end_courses
          }, {

    "courses" will be the main entry point for our tag library, and as such
    needs to do some special things to set itself up. Hence, it uses a
    "special" type, and provides its own handlers to handle the start and
    end tag events. These handlers will be responsible for setting up
    $_xsp_axkit_xsp_objecttaglib_demo_courses, used in the following tags,
    and looping over the possible courses, setting
    $_xsp_axkit_xsp_objecttaglib_demo_course appropriately.

          }, {
            tag    => 'name',
            target => 'course'
          }, {
            tag    => 'code',
            target => 'course'
          }, {
            tag    => 'description',
            target => 'course',
            type   => 'as_xml'
          }, {
            tag    => 'summary',
            target => 'course',
            type   => 'as_xml'
          }, {

    When we see the "name" tag, we call the "name" method on each
    $_xsp_axkit_xsp_objecttaglib_demo_course object within the loop.
    Similarly, the "code" tag calls the "code" method on the same object.

    The "description" and "summary" tags call the "description" and
    "summary" methods on each course object with the loop, this time making
    sure that the result is valid XML instead of plain text. (This is
    because we store the description in the database as XML, and don't want
    it escaped before AxKit throws it onto the page.)

          }, {
            tag      => 'presentations',
            target   => 'course',
            type     => 'loop',
            iterator => 'presentation'
          }, {

    Each course object has a "presentations" method, which is wrapped by the
    "presentations" tag. This method returns a list of objects representing
    the presentations of a course; the "presentations" tag sets up a loop,
    with $_xsp_axkit_xsp_objecttaglib_demo_presentation as the iterator.
    Hence, inside of a "presentations" tag, "target => "presentation"" will
    cause the method to be called on each presentation object in turn.

          }, {
            tag    => 'size',
            key    => 'calculateSize',
            target => 'presentation',
            notnull => 1
          }, {

    Like the course "name" tag, we'll declare a "size" tag for the
    "presentation" object.

          }, {
            tag      => 'prerequisites',
            target   => 'course',
            type     => 'loop',
            iterator => 'course'
          }

    This is slightly dirty. We want a "prerequisites" tag to refer to other
    course objects, namely, the courses which are required for admission to
    the current course. ie:

        <demo:prerequisites>
          <prerequisite>
            <name><demo:name/></name>
            <code><demo:code/></code>
          </prerequisite>
        </demo:prerequisites>

    So when we see the "prerequisites" tag, we call the "prerequisites"
    method on our "course" target, $_xsp_axkit_xsp_coursebooking_course.
    This returns a list of new prerequisite objects, which we loop over.
    ("type =" "loop">)

    Our loop iterator will be $_xsp_axkit_xsp_objecttaglib_demo_course
    itself, so the other tags will work properly on the iterated courses.

    Some code is worth a thousand words. The generated perl will look
    something like this:

        for my $_xsp_axkit_xsp_objecttaglib_demo_course
            ($_xsp_axkit_xsp_objecttaglib_demo_course->prerequisites) {
            ... $_xsp_axkit_xsp_objecttaglib_demo_course->name ...
        }

    Because we want to use the "name" tag within the prerequisites and the
    courses, we chose the slightly dirty method above. We could also have
    declared a new tag called "reqname" and chosen a cleaner iterator like
    so

          }, {
            tag      => 'prerequisites',
            target   => 'course',
            type     => 'loop',
            iterator => 'prerequisite'
          }, {
            tag      => 'reqname',
            target   => 'prerequisite'
          }

    and then use slightly different XSP like this

        <demo:prerequisites>
          <prerequisite>
            <name><demo:reqname/></name>
            <code><demo:code/></code>
          </prerequisite>
        </demo:prerequisites>

    Here's another quick example:

        our @specification = (
            { tag => "person", type => "special",
                                start => \&start_person, end => \&end_person },
            { tag => "name", key => "cn", target => 'person'},
            ...
        );

    This comes from a wrapper around LDAP. As before, the "person" tag at
    the top level has two subroutines to set up the "person" target. (which
    in this case will be $_xsp_axkit_xsp_ldap_person) When a "name" tag is
    seen inside of the "person" tag, a method is called on that target. This
    time, we use "key" to say that the method name is actually "cn", rather
    than "name". Hence the following XSP:

        <b:person dn="foo">
           <b:name/>
        </b:person>

    generates something like this:

        {
        my $_xsp_axkit_xsp_ldap_person = somehow_get_ldap_object(dn => "foo");

           ...
           $_xsp_axkit_xsp_ldap_person->cn();
           ...
        }

    All clear?

SEE ALSO
    AxKit::XSP::ObjectTaglib::Demo

AUTHOR
        Christopher H. Laco
        CPAN ID: CLACO
        claco@chrislaco.com
        http://today.icantfocus.com/blog/

AUTHOR EMERITUS
    The original version was created by Simon Cozens.

