Excel::Template::Iterator - Excel::Template::Iterator documentation


Excel-Template documentation Contained in the Excel-Template distribution.

Index


Code Index:

NAME

Top

Excel::Template::Iterator

PURPOSE

Top

This is meant for internal use only. Documentation is provided for subclassing.

NODE NAME

Top

None

INHERITANCE

Top

None

ATTRIBUTES

Top

None

CHILDREN

Top

None

AFFECTS

Top

This is a helper class for LOOP

DEPENDENCIES

Top

None

METHODS

Top

can_continue

Determines if the iterator can continue.

Currently, this wraps more_params(), but there other possible situations, such as the page ending.

more_params

Determines if the iterator for the loop has more parameters that it can consume

next

Go to the next iteration of the loop

AUTHOR

Top

Rob Kinyon (rob.kinyon@gmail.com)

SEE ALSO

Top

LOOP


Excel-Template documentation Contained in the Excel-Template distribution.

package Excel::Template::Iterator;

use strict;

BEGIN {
    use vars qw(@ISA);
    @ISA = qw(Excel::Template::Base);

    use Excel::Template::Base;
}

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

    unless (Excel::Template::Factory::isa($self->{CONTEXT}, 'CONTEXT'))
    {
        die "Internal Error: No context object passed to ", __PACKAGE__, $/;
    }

    $self->{MAXITERS} ||= 0;

    # This is the index we will work on NEXT, in whatever direction the
    # iterator is going.
    $self->{INDEX} = -1;

    # This is a short-circuit parameter to let the iterator function in a
    # null state.
    $self->{NO_PARAMS} = 0;
    unless ($self->{NAME} =~ /\w/)
    {
        $self->{NO_PARAMS} = 1;

        warn "INTERNAL ERROR: 'NAME' was blank was blank when passed to ", __PACKAGE__, $/ if $^W;

        return $self;
    }

    # Cache the reference to the appropriate data.
    $self->{DATA} = $self->{CONTEXT}->param($self->{NAME});

    unless (ref $self->{DATA} eq 'ARRAY')
    {
        $self->{NO_PARAMS} = 1;
        warn "'$self->{NAME}' does not have a list of parameters", $/ if $^W;

        return $self;
    }

    unless (@{$self->{DATA}})
    {
        $self->{NO_PARAMS} = 1;
    }

    $self->{MAX_INDEX} = $#{$self->{DATA}};

    return $self;
}

sub enter_scope
{
    my $self = shift;

    return 0 if $self->{NO_PARAMS};

    for my $x ($self->{DATA}[$self->{INDEX}])
    {
        $x->{uc $_} = delete $x->{$_} for keys %$x;
    }

    push @{$self->{CONTEXT}{PARAM_MAP}}, $self->{DATA}[$self->{INDEX}];

    return 1;
}

sub exit_scope
{
    my $self = shift;

    return 0 if $self->{NO_PARAMS};

    # There has to be the base parameter map and at least the one that
    # Iterator::enter_scope() added on top.
    @{$self->{CONTEXT}{PARAM_MAP}} > 1 ||
        die "Internal Error: ", __PACKAGE__, "'s internal param_map off!", $/;

    pop @{$self->{CONTEXT}{PARAM_MAP}};

    return 1;
}

sub can_continue
{
    my $self = shift;

    return 0 if $self->{NO_PARAMS};

    return 1 if $self->more_params;

    return 0;
}

sub more_params
{
    my $self = shift;

    return 0 if $self->{NO_PARAMS};

    return 1 if $self->{MAX_INDEX} > $self->{INDEX};

    return 0;
}

# Call this method BEFORE incrementing the index to the next value.
sub _do_globals
{
    my $self = shift;

    my $data = $self->{DATA}[$self->{INDEX}];

    # Perl's arrays are 0-indexed. Thus, the first element is at index "0".
    # This means that odd-numbered elements are at even indices, and vice-versa.
    # This also means that MAX (the number of elements in the array) can never
    # be the value of an index. It is NOT the last index in the array.

    $data->{'__FIRST__'} ||= ($self->{INDEX} == 0);
    $data->{'__INNER__'} ||= (0 < $self->{INDEX} && $self->{INDEX} < $self->{MAX_INDEX});
    $data->{'__LAST__'}  ||= ($self->{INDEX} == $self->{MAX_INDEX});
    $data->{'__ODD__'}   ||= !($self->{INDEX} % 2);

    return 1;
}

sub next
{
    my $self = shift;

    return 0 if $self->{NO_PARAMS};

    return 0 unless $self->more_params;

    $self->exit_scope;

    $self->{INDEX}++;

    $self->_do_globals;

    $self->enter_scope;

    return 1;
}

# This method doesn't seem to be used ...
# If it is reinstated, here's the POD for it
#=head2 back_up
#
#Go to the previous iteration of the loop
#
#sub back_up
#{
#    my $self = shift;
#
#    return 0 if $self->{NO_PARAMS};
#
#    $self->exit_scope;
#
#    $self->{INDEX}--;
#
#    $self->_do_globals;
#
#    $self->enter_scope;
#
#    return 1;
#}

# This method doesn't seem to be used ...
# If it is reinstated, here's the POD for it
#=head2 reset
#
#Resets the iterator
#
#sub reset
#{
#    my $self = shift;
#
#    return 0 if $self->{NO_PARAMS};
#
#    $self->{INDEX} = -1;
#
#    return 1;
#}

1;
__END__