Para::Frame::List - Methods for list manipulation
# The right way:
my $list = Para::Frame::List->new( \@biglist ); my( $value, $error ) = $list->get_first; while(! $error ) { # ... my code } continue { ( $value, $error ) = $list->get_next; }
# The risky way, for lists that doesn't contain false values:
my $list = Para::Frame::List->new( \@biglist ); $list->reset; # if used before... while( my $value = $list->get_next_nos ) { # ... my code }
# The lazy way:
my $list = Para::Frame::List->new( \@biglist ); foreach my $value ( $list->as_array ) { # ... my code }
LOOK! REDEFINES shift, push, pop, unshift, splice, join, index
The object is overloaded to be used as a ref to the list it contains. All list operations can be used as usual. Example:
my $l = Para::Frame::List->new( \@biglist ); my $first_element = $l->[0]; my $last_element = pop @$l;
The iteration methods is compatible with (and inherits from) Template::Iterator. (The iterator status codes are taken from Template::Constants.)
CGI query parameters reserved for use with some methods are:
order direction table_page
Since Para::Frame is built for use with Template, it implements the Template::Iterator class.
But this class is extanded to provide more useful things. Primarely:
* Iteration * Initialize list elements on demand * Split list into pages * Access metadata about the list * Modify the list
There are a large amount of diffrent implementation of iterators and List classes. I will try to keep the method names clear and mention choises from other modules.
This module is subclassable.
We should implement all methods in a way that allow subclasses to only initiate and hold the specified used parts in memory, maby by using tie.
TODO: Implement the rest of the array modification methods()
TODO: Use a tied array var for overload, in order to update metadata on change.
Subclasses that don't want to load the whole list in memory should implement:
max() size() get_next_raw() get_prev_raw()
Subclasses that want to construct the list on demand should implement:
populate_all()
$l = $class->new( \@list ) $l = $class->new( \@list, \%params )
Availible params are:
page_size (default is 20 ) display_pages (default is 10 ) limit_pages (default is 0 == unlimited) limit (default is 0 == unlimited) limit_display (default is 0 == unlimited) materializer (default is undef == list is material) type (default is undef) allow_undef (default is undef)
The first argument may be a Para::Frame::List object, in which case it's content is copied to this new list.
If the first argument is undef, the list is marked as unpopulated
See also: /set_materializer
Compatible with Template::Iterator/new.
Returns:
A an object blessed in $class
$l = $class->new( $any ) $l = $class->new( $any, \%params )
The same as /new but accepts more forms of lists.
If $any
is a Para::Frame::List object, or an array ref, it will
be sent to the /new constructor.
For all other defined values of $any, it will be taken as a list of
that single element and sent to /new as [$any]
.
If $any
is undef, the constructor /new_empty will be used.
$l = $class->new_empty()
This is an optimized form of /new that is faster and more memory efficient than /new but should behave in the same way.
$l->init
Called by /new for additional initializing. Subclasses can use this for filling the list with data or adding more properties.
$l->set_materializer( $materializer )
The materializer can be used to format an element before it's returned from the list. This can be used for turning a record id to an object. With a materializer, the objectification or formatting of the data can be done on demand which will save a lot of computation in the case of large lists like search results.
$materializer
should be a subref that takes the params $l, $i
where $i
is the index of the element to materialize. The
materializer sub should return the materialized form of the element.
See /materialize_all and /new.
Returns:
The given $materializer
subref.
$l->as_arrayref()
See also /get_all and /as_list. Most other modules misses a comparable method.
This method is used by the array dereferencing overload.
Returns:
A ref to the internal list of elements returned by /materialize_all.
implemented concatenate_by_overload()
stringify_by_overload() method defined
$l->as_arrayref()
Returns the internal arrayref to the unmaterialized elements.
$l->as_list()
Compatible with Template::Iterator.
See also /get_all and /elements.
Returns:
A ref to the internal list of elements returned by /materialize_all.
$l->as_listobj()
Retruns: the object itself
$l->as_array()
Similar to List::Object/array and IO::Handle/getlines. See also /get_all and /as_list.
Returns:
The list as a list. (Not a ref) (And not realy an array either...)
$l->as_raw_array()
Returns the unmaterialized list as a list of elements (not ref).
$l->populate_all()
Reimplement this if the content should be set on demand in a subclass.
Returns:
The raw data listref of unmateralized elements.
$l->on_populate_all()
$l->materialize_all()
If /materializer is set, calls it for each unmaterialized element and returns a ref to an array of the materialized elements
In no materialization is needed, just returns the existing data as an array ref.
$l->from_page( $pagenum ) $l->from_page
Returns a ref to a list of elements corresponding to the given
$page
based on the /page_size. If no $pagenum
is given, takes the value from query param table_page or 1.
... I have looked at Array::Window but will not use it.
$l->slice( $start ) $l->slice( $start, $end ) $l->slice( $start, $end, \%args )
Similar to Class::DBI::Iterator/slice.
If %args
is not given, clones the args of $l
.
Uses /set_index and /get_next_raw and /index.
Returns:
A Para::Frame::List created with the same /type, /allow_undef and /materializer args.
$l->set_index($pos)
Similar to Tie::Array::Iterable/set_index and IO::Seekable/seek. Most iterator classes doesn't have a comparable method.
Valid positions range from -1 (before first element) to $size + 1
(after last element).
If $pos
is -1
, calls /reset.
$l->store
Stores the object in the session for later retrieval by Para::Frame::Session/list
DEPRECATED
$l->id
Returns the id
given to this object from /store in the
Para::Frame::Session.
$l->list_id
Returns the id
given to this object from /store in the
Para::Frame::Session.
$l->pages
Returns the number of pages this list will take given /page_size.
$l->page_size
Returns the page_size
set for this object.
$l->pagelist( $pagenum ) $l->pagelist
Returns a widget for navigating between the pages. If no $pagenum
is given, takes the value from query param table_page or 1.
If only one page, returns an empty string.
Example:
[% USE Sorted_table('created','desc') %] [% usertable = cached_select_list("from users order by $order $direction") %] <table> <tr> <th>[% sort("Skapad",'created','desc') %]</th> <th>[% sort("Namn",'username') %]</th> </tr> <tr><th colspan="2">[% usertable.size %] users</th></tr> <tr><th colspan="2"> [% usertable.pagelist %]</th></tr> [% FOREACH user IN usertable.from_page %] [% tr2 %] <td>[% user.created %]</td> <td>[% user.name %]</td> </tr> [% END %] </table>
This uses Para::Frame::Template::Plugin::Sorted_table, Para::Frame::DBIx/cached_select_list, Para::Frame::Template::Components/sort, /size, this pagelist, Template::Manual::Directives/Loop Processing and Para::Frame::Template::Components/tr2.
$l->pagenum
Returns the current page number, as given by the query param table_page
.
$l->set_page_size( $page_size )
Sets and returns the given $page_size
$l->display_pages
Returns how many pages that should be listed by /pagelist.
Sets and returns the given /display_pages.
Sets and returns the given /limit_pages.
$l->limit_pages
Returns the last page number that should be listed by /pagelist.
$l->limit_display
Returns how many results that will be shown then listed as pages
Sets and returns the given /limit_display.
$l->as_string
Returns a string representation of the list. Using as_string
for
elements that isn't plain scalars.
$l->set_limit( $limit )
Limit the number of elements in the list.
A limit of $limit
or undef
means no limit.
Setting a limit smaller than the original length will make the elements beyond the limit unavailible, if they already was populated. Later setting a larger limit will not make more of the elements availible.
The limit is applied directly.
The number of elements before the applied limit, if known, can be retrieved from /original_size.
The limit may be larger than the elements in the list.
Similar to IO::Seekable/truncate except that it doesn't delete anything. Similar to limit in SQL.
TODO: Check for limit on array change
Returns:
The limit set, or 0
$l->limit()
Returns:
The current limit set by /set_limit
$l->get_first
The first record is returned, if defined, along with the STATUS_OK value. If there is no target data, or the data is an empty set, then undef is returned with the STATUS_DONE value as the second element in the return list.
Compatible with Template::Iterator. Similar to List::Object/first and Class::DBI::Iterator/first. Not the same as ouer /first.
Calls /reset if the iterator index isn't at the start (at -1).
$l->get_first_nos
The same as /get_first except that it only returns ONE value, that may be undef.
$l->get_last
The last record is returned, if defined, along with the STATUS_OK value. If there is no target data, or the data is an empty set, then undef is returned with the STATUS_DONE value as the second element in the return list.
Similar to List::Object/last. Not the same as ouer /last.
$l->get_last_nos
The same as /get_last except that it only returns ONE value, that may be undef.
$l->reset()
Sets the index to -1
, before the first element.
Similar to Array::Iterator::Reusable/reset, Class::DBI::Iterator/reset, Class::PObject::Iterator/reset, Tie::Array::Iterable/from_start and List::Object/rewind.
Returns:
true
$l->get_next()
Called repeatedly to access successive elements in the data set. Is usually called after calling /get_first.
Compatible with Template::Iterator/get_next. Most other Iterator
classes call this method next()
. But our /next is not the same.
Similar to List::Object/next, Array::Iterator/getNext,
Class::DBI::Iterator/next, Class::PObject::Iterator/next,
Tie::Array::Iterable/next, Iterator/value,
IO::Seekable/getline and Java next()
.
This method is implemented with /get_next_raw and /materialize.
Returns
The next element and a status as the two elements in the return list
$l->get_next_nos()
The same as /get_next except that it only returns ONE value, that may be undef. (Get Next with NO Status)
$l->get_next_raw()
Used as a backend for /get_next.
Increments the index.
Returns:
The next element and a status
$l->get_prev()
May be called after calling /get_last.
Similar to Array::Iterator::BiDirectional/getPrevious,
Tie::Array::Iterable/prev and Java previous()
.
See also /prev.
This method is implemented with /get_prev_raw and /materialize.
Returns
The prev element and a status as the two elements in the return list
$l->get_prev_nos()
The same as /get_prev except that it only returns ONE value, that may be undef.
$l->get_prev_raw()
Used as a backend for /get_prev.
Returns:
The prev element and decrement the index.
$l->get_all
Method which returns all remaining items in the iterator as a Perl list reference. May be called at any time in the life-cycle of the iterator. The /get_first method will be called automatically if necessary, and then subsequent /get_next calls are made, storing each returned result until the list is exhausted.
Compatible with Template::Iterator/get_all.
Sets the index on the last element. (Not the place after the element.)
Returns:
A ref to an array of the remaining elements, materialized.
If iterator already at the last index or later, returns undef
as
the first value and Template::Constants/STATUS_DONE as the second.
$l->size()
Similar to List::Object/count, Array::Iterator/getLength,
Class::DBI::Iterator/count,
Class::MakeMethods::Template::Generic/count and java getSize()
.
Compatible with Template::Iterator/size and Template::Manual::VMethods/List Virtual Methods
Returns:
The number of elements in this list
$l->size_limited()
Returns: the /size, constraining to given /limit_display
$l->max
Returns the maximum index number (i.e. the index of the last element) which is equivalent to size() - 1.
Compatible with Template::Iterator/max and Template::Manual::VMethods/List Virtual Methods
$l->max_limited()
Returns: the /max, constraining to given /limit_display
$l->index()
Returns the current index number which is in the range 0 to max().
Template::Iterator/index has the range 0
to /max. This
module allows the range -1
to /max+1
.
Similar to Array::Iterator/currentIndex,
Tie::Array::Iterable/index, IO::Seekable/tell and Java
getPosition
.
Heres hoping that nothing breaks...
$l->count()
Returns the current iteration count in the range 1 to size(). This is equivalent to index() + 1.
Compatible with Template::Iterator/count.
$l->first
Returns a boolean value to indicate if the iterator is currently on
the first iteration of the set. Ie, index 0
.
Compatible with Template::Iterator/first and Template::Manual::VMethods/List Virtual Methods
.
Similar to Array::Iterator::Circular/isStart and Tie::Array::Iterable/at_start.
See also /get_first.
$l->last
Returns a boolean value to indicate if the iterator is currently on the last iteration of the set.
Compatible with Template::Iterator/last and Template::Manual::VMethods/List Virtual Methods
Similar to Array::Iterator::Circular/isEnd, Iterator/is_exhausted, Tie::Array::Iterable/at_end and IO::Seekable/eof.
See also /get_last.
$l->prev
Returns the previous item in the data set, or undef if the iterator is on the first item.
This does not change the iterator index.
Compatible with Template::Iterator/prev.
Similar to Array::Iterator::BiDirectional/lookBack.
See also /get_prev.
$l->next
Returns the next item in the data set or undef if the iterator is on the last item.
This does not change the iterator index.
Compatible with Template::Iterator/next.
$l->has_next
Similar to List::Object/has_next, Array::Iterator/hasNext and
Java hasNext
.
Returns:
A bool
$l->has_prev
Similar to Array::Iterator::BiDirectional/hasPrevious and Java
hasPrevious
.
Returns:
A bool
$l->current()
Similar to Array::Iterator/current and Tie::Array::Iterable/value.
Implemented with /get_next
Returns:
The element (materialized) at the current index.
$l->get_by_index( $index )
Similar to List::Object/get.
Implemented with /set_index and /get_next.
Returns:
The element (materialized) at $index
. (First element has index 0).
Or undef
$l->clear()
Similar to List::Object/clear
$l->randomized
Doesn't modify the object
Returns:
A new list with the content in random order, but with the same properties
The class or datatype of all the content in the list
TODO: Validate content with this
$l->push( @elements )
Returns: The number of elements added
$l->push_uniq( @elements )
Only add elements not already in the list
Returns: The number of elements added
$l->unshift_uniq( @elements )
Only add elements not already in the list
Returns: The number of elements added
$l->join() $l->join($separator)
$separator
defaults to the empty string.
Returns: A scalar string of all elements concatenated
Compatible with Template::Manual::VMethods/List Virtual Methods
$l->complement($l2)
Returns a list with the elements from $l not found in $l2
$l->uniq()
Returns a list with multiple list items filtered out. Operates on the unmaterialized items. If nothing filtered, returns the same object.
$l->merge( $list2, $list3, ... )
Returns a list composed of zero or more other lists. The original lists are not modified. Filters out parametrs that are not lists. Always returns a new list, even if it has the same content as the calling list.
Uses the cloned args of the calling list.
Compatible with Template::Manual::VMethods/List Virtual Methods
$l->reverse()
Returns a list composed of the items in reverse order.
Uses the cloend args of the calling list.
Compatible with Template::Manual::VMethods/List Virtual Methods
$l->flatten()
Creates a new list with any list elements flatten to it's elements. Recursively. Flattens Para::Frame::List objs and unblessed arrayrefs.
Always returns a new list object of the same class and with the same properties.
TODO: Make this a materializer function, to handle large lists
$list->resort( ... )
Same as /sorted, but modifies the existing object, rather than creating a new object.
If no params given, the cgi params order
and direction
will be
used.
Will not resort if the object sortkey property is the same
Returns:
The same list object
$l->sysdesig
Return a SCALAR string with the elements sysdesignation concatenated with
' / '
.
$l->sum
$list->sorted() $list->sorted( $attr ) $list->sorted( $attr, $dir, $type ) $list->sorted( [$attr1, $attr2, ...] ) $list->sorted( [$attr1, $attr2, ...], $dir, $type ) $list->sorted( { on => $attr, dir => $dir, type => $type } ) $list->sorted( [{ on => $attr1, dir => $dir1, type => $type1 }, { on => $attr2, dir => $dir2, type => $type2 }, ... ] )
Returns a list of object, sorted by the selected proprty of the object.
This method assumes that the list only contains objects and that all of them has a similar interface.
The default sorting attribute is the stringification of the object (or the string itself if it's not an object).
$dir
is the direction of the sort. It can be asc
or desc
.
$attr
can be of the form a1.a2.a3
which translates to an attribute
lookup in several steps. For example; $list-
sorted('email.host')>
The sorting will be done as strings with <cmp>. You can get a string
sort by using $type numeric
.
Examples:
Loop over the name arcs of a node, sorted by firstly on the is_of_language code and secondly on the weight in reverse order:
[% FOREACH arc IN n.arc_list('name').sorted(['obj.is_of_language.code',{on='obj.weight' dir='desc'}]) %]
Returns:
A List object with 0 or more elements.
Exceptions:
Dies if given faulty parameters.
$l->$method( @args )