1 #============================================================= -*-Perl-*-
7 # Module defining an iterator class which is used by the FOREACH
8 # directive for iterating through data sets. This may be
9 # sub-classed to define more specific iterator types.
12 # Andy Wardley <abw@wardley.org>
15 # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
17 # This module is free software; you can redistribute it and/or
18 # modify it under the same terms as Perl itself.
20 #============================================================================
22 package Template::Iterator;
26 use base 'Template::Base';
27 use Template::Constants;
28 use Template::Exception;
29 use Scalar::Util qw(blessed);
31 use constant ODD => 'odd';
32 use constant EVEN => 'even';
35 our $DEBUG = 0 unless defined $DEBUG;
38 #========================================================================
39 # ----- CLASS METHODS -----
40 #========================================================================
42 #------------------------------------------------------------------------
43 # new(\@target, \%options)
45 # Constructor method which creates and returns a reference to a new
46 # Template::Iterator object. A reference to the target data (array
47 # or hash) may be passed for the object to iterate through.
48 #------------------------------------------------------------------------
52 my $data = shift || [ ];
53 my $params = shift || { };
55 if (ref $data eq 'HASH') {
56 # map a hash into a list of { key => ???, value => ??? } hashes,
57 # one for each key, sorted by keys
58 $data = [ map { { key => $_, value => $data->{ $_ } } }
61 elsif (blessed($data) && $data->can('as_list')) {
62 $data = $data->as_list();
64 elsif (ref $data ne 'ARRAY') {
65 # coerce any non-list data into an array reference
76 #========================================================================
77 # ----- PUBLIC OBJECT METHODS -----
78 #========================================================================
80 #------------------------------------------------------------------------
83 # Initialises the object for iterating through the target data set. The
84 # first record is returned, if defined, along with the STATUS_OK value.
85 # If there is no target data, or the data is an empty set, then undef
86 # is returned with the STATUS_DONE value.
87 #------------------------------------------------------------------------
91 my $data = $self->{ _DATA };
93 $self->{ _DATASET } = $self->{ _DATA };
94 my $size = scalar @$data;
97 return (undef, Template::Constants::STATUS_DONE) unless $size;
99 # initialise various counters, flags, etc.
100 @$self{ qw( SIZE MAX INDEX COUNT FIRST LAST ) }
101 = ( $size, $size - 1, $index, 1, 1, $size > 1 ? 0 : 1, undef );
102 @$self{ qw( PREV NEXT ) } = ( undef, $self->{ _DATASET }->[ $index + 1 ]);
104 return $self->{ _DATASET }->[ $index ];
109 #------------------------------------------------------------------------
112 # Called repeatedly to access successive elements in the data set.
113 # Should only be called after calling get_first() or a warning will
114 # be raised and (undef, STATUS_DONE) returned.
115 #------------------------------------------------------------------------
119 my ($max, $index) = @$self{ qw( MAX INDEX ) };
120 my $data = $self->{ _DATASET };
122 # warn about incorrect usage
123 unless (defined $index) {
124 my ($pack, $file, $line) = caller();
125 warn("iterator get_next() called before get_first() at $file line $line\n");
126 return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
129 # if there's still some data to go...
131 # update counters and flags
133 @$self{ qw( INDEX COUNT FIRST LAST ) }
134 = ( $index, $index + 1, 0, $index == $max ? 1 : 0 );
135 @$self{ qw( PREV NEXT ) } = @$data[ $index - 1, $index + 1 ];
136 return $data->[ $index ]; ## RETURN ##
139 return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
144 #------------------------------------------------------------------------
147 # Method which returns all remaining items in the iterator as a Perl list
148 # reference. May be called at any time in the life-cycle of the iterator.
149 # The get_first() method will be called automatically if necessary, and
150 # then subsequent get_next() calls are made, storing each returned
151 # result until the list is exhausted.
152 #------------------------------------------------------------------------
156 my ($max, $index) = @$self{ qw( MAX INDEX ) };
159 # handle cases where get_first() has yet to be called.
160 unless (defined $index) {
161 my ($first, $status) = $self->get_first;
163 # refresh $max and $index, after get_first updates MAX and INDEX
164 ($max, $index) = @$self{ qw( MAX INDEX ) };
166 # empty lists are handled here.
167 if ($status && $status == Template::Constants::STATUS_DONE) {
168 return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
173 ## if there's nothing left in the iterator, return the single value.
174 unless ($index < $max) {
179 # if there's still some data to go...
182 push @data, @{ $self->{ _DATASET } } [ $index..$max ];
184 # update counters and flags
185 @$self{ qw( INDEX COUNT FIRST LAST ) }
186 = ( $max, $max + 1, 0, 1 );
188 return \@data; ## RETURN ##
191 return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
196 shift->{ COUNT } % 2 ? 1 : 0
200 shift->{ COUNT } % 2 ? 0 : 1
204 shift->{ COUNT } % 2 ? ODD : EVEN;
208 #------------------------------------------------------------------------
211 # Provides access to internal fields (e.g. size, first, last, max, etc)
212 #------------------------------------------------------------------------
216 my $item = $AUTOLOAD;
218 return if $item eq 'DESTROY';
220 # alias NUMBER to COUNT for backwards compatability
221 $item = 'COUNT' if $item =~ /NUMBER/i;
223 return $self->{ uc $item };
227 #========================================================================
228 # ----- PRIVATE DEBUG METHODS -----
229 #========================================================================
231 #------------------------------------------------------------------------
234 # Debug method which returns a string detailing the internal state of
235 # the iterator object.
236 #------------------------------------------------------------------------
241 " Data: ", $self->{ _DATA }, "\n",
242 " Index: ", $self->{ INDEX }, "\n",
243 "Number: ", $self->{ NUMBER }, "\n",
244 " Max: ", $self->{ MAX }, "\n",
245 " Size: ", $self->{ SIZE }, "\n",
246 " First: ", $self->{ FIRST }, "\n",
247 " Last: ", $self->{ LAST }, "\n",
259 Template::Iterator - Data iterator used by the FOREACH directive
263 my $iter = Template::Iterator->new(\@data, \%options);
267 The C<Template::Iterator> module defines a generic data iterator for use
268 by the C<FOREACH> directive.
270 It may be used as the base class for custom iterators.
272 =head1 PUBLIC METHODS
276 Constructor method. A reference to a list of values is passed as the
277 first parameter. Subsequent calls to L<get_first()> and L<get_next()> calls
278 will return each element from the list.
280 my $iter = Template::Iterator->new([ 'foo', 'bar', 'baz' ]);
282 The constructor will also accept a reference to a hash array and will
283 expand it into a list in which each entry is a hash array containing
284 a 'C<key>' and 'C<value>' item, sorted according to the hash keys.
286 my $iter = Template::Iterator->new({
291 This is equivalent to:
293 my $iter = Template::Iterator->new([
294 { key => 'bar', value => 'Bar Item' },
295 { key => 'foo', value => 'Foo Item' },
298 When passed a single item which is not an array reference, the constructor
299 will automatically create a list containing that single item.
301 my $iter = Template::Iterator->new('foo');
303 This is equivalent to:
305 my $iter = Template::Iterator->new([ 'foo' ]);
307 Note that a single item which is an object based on a blessed ARRAY
308 references will NOT be treated as an array and will be folded into
309 a list containing that one object reference.
311 my $list = bless [ 'foo', 'bar' ], 'MyListClass';
312 my $iter = Template::Iterator->new($list);
316 my $iter = Template::Iterator->new([ $list ]);
318 If the object provides an C<as_list()> method then the L<Template::Iterator>
319 constructor will call that method to return the list of data. For example:
321 package MyListObject;
325 bless [ @_ ], $class;
330 my $list = MyListObject->new('foo', 'bar');
331 my $iter = Template::Iterator->new($list);
333 This is then functionally equivalent to:
335 my $iter = Template::Iterator->new([ $list ]);
337 The iterator will return only one item, a reference to the C<MyListObject>
340 By adding an C<as_list()> method to the C<MyListObject> class, we can force
341 the C<Template::Iterator> constructor to treat the object as a list and
342 use the data contained within.
344 package MyListObject;
355 my $list = MyListObject->new('foo', 'bar');
356 my $iter = Template::Iterator->new($list);
358 The iterator will now return the two items, 'C<foo>' and 'C<bar>', which the
359 C<MyObjectList> encapsulates.
363 Returns a C<($value, $error)> pair for the first item in the iterator set.
364 The C<$error> returned may be zero or undefined to indicate a valid datum
365 was successfully returned. Returns an error of C<STATUS_DONE> if the list
370 Returns a C<($value, $error)> pair for the next item in the iterator set.
371 Returns an error of C<STATUS_DONE> if all items in the list have been
376 Returns a C<(\@values, $error)> pair for all remaining items in the iterator
377 set. Returns an error of C<STATUS_DONE> if all items in the list have been
382 Returns the size of the data set or undef if unknown.
386 Returns the maximum index number (i.e. the index of the last element)
387 which is equivalent to L<size()> - C<1>.
391 Returns the current index number which is in the range C<0> to L<max()>.
395 Returns the current iteration count in the range C<1> to L<size()>. This is
396 equivalent to L<index()> + C<1>.
400 Returns a boolean value to indicate if the iterator is currently on
401 the first iteration of the set.
405 Returns a boolean value to indicate if the iterator is currently on
406 the last iteration of the set.
410 Returns the previous item in the data set, or C<undef> if the iterator is
415 Returns the next item in the data set or C<undef> if the iterator is on the
420 Returns the text string C<even> or C<odd> to indicate the parity of the
421 current iteration count (starting at 1). This is typically used to create
422 striped I<zebra tables>.
425 [% FOREACH name IN ['Arthur', 'Ford', 'Trillian'] -%]
426 <tr class="[% loop.parity %]">
432 This will produce the following output:
446 You can then style the C<tr.odd> and C<tr.even> elements using CSS:
449 background-color: black;
454 background-color: white;
460 Returns a boolean (0/1) value to indicate if the current iterator count
461 (starting at 1) is an odd number. In other words, this will return a true
462 value for the first iterator, the third, fifth, and so on.
466 Returns a boolean (0/1) value to indicate if the current iterator count
467 (starting at 1) is an even number. In other words, this will return a true
468 value for the second iteration, the fourth, sixth, and so on.
472 Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
476 Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
478 This module is free software; you can redistribute it and/or
479 modify it under the same terms as Perl itself.
489 # perl-indent-level: 4
490 # indent-tabs-mode: nil
493 # vim: expandtab shiftwidth=4: