NAME
List::Filter - named, persistent, shared lists of patterns
SYNOPSIS
use List::Filter;
my $filter = List::Filter->new(
{ name => 'skip_boring_stuff',
terms => ['-\.vb$', '\-.js$'],
method => 'skip_boring_stuff',
description => "Skip the really boring stuff",
modifiers => "xi",
} );
# If non-standard behavior is desired in locating the methods via plugins
my $filter = List::Filter->new(
{ name => 'skip_boring_stuff',
terms => ['-\.vb$', '\-.js$'],
method => 'skip_boring_stuff',
description => "Skip the really boring stuff",
modifiers => "xi",
plugin_root => 'List::Filter::Filters',
plugin_exceptions => ["List::Filter::Transforms::NotThisOne"],
} );
# Alternately:
my $filter = List::Filter->new(); # creates an *empty* filter
my @terms = ['-\.vb$', '-\.js$'];
$filter->set_name('skip_dull');
$filter->set_terms( \@terms );
$filter->set_method('skip_boring_stuff');
$filter->set_description(
"Skip the really boring stuff");
$filter->set_modifiers( "xi" );
# using a filter (using it's internally defined "method")
my $output_items = $filter->apply( \@input_items );
# using a filter, specifying an alternate "method"
my $output_items = $filter->apply( \@input_items, "do_it_like_this" );
DESCRIPTION
The List::Filter system is a generalized, extensible way of filtering a list of items by apply a stack of perl regular expressions, with a persistant storage mechanism to allow the sharing of filters between different applications.
A List::Filter filter would just be a container object (a hashref with some accessor code), except that it also has an internally generated "dispatcher" object, so that it knows how to "apply" itself.
The "method" attribute of a filter object is indeed the name of a method, but not one defined inside this module. Instead there's a "plug-in" system that allows the definition of new methods without modification of the existing code.
See List::Filter::Project for documentation of the system.
OBJECT ATTRIBUTES
filter attributes (stored associated with the given name)
- name
-
The name of the search filter.
- terms
-
A list of filter items, e.g. search terms (essentially regexps).
- method
-
The default method used to apply the search terms.
- modifiers
-
Default modifiers to be applied to the search terms (essentially, regexp modifiers, e.g. "i").
- description
-
A short description of the search filter.
- dispatcher
-
Internally used field that stores the dispatcher object, a handle used to apply the filter according to it's "method".
- storage_handler
-
### TODO weirdly enough, I can't figure out where this gets set. ### if it isn't set, then the save method can't work. ### but if the following flag is set, the apply method calls ### the save method... do I ever set this flag at this level?
- save_filters_when_used
-
### TODO
METHODS
- new
-
Instantiates a new List::Filter object.
Takes an optional hashref as an argument, with named fields identical to the names of the object attributes:
name description terms method modifiers
With no arguments, the newly created filter will be empty.
There is also the attribute:
storage_handler
which is intended to point to the storage handler set-up so that the filter has the capbility of saving itself to storage later. See "MOTIVATION" below.
There's a related flag (typically set by the storage handler):
save_filters_when_used
There are two additional optional arguments,
plugin_root plugin_exceptions
That are used in creating the dispatcher object which locates the code used to apply the filter (typically as specified by the "method" attribute):
- init
-
Initialize object attributes and then lock them down to prevent accidental creation of new ones.
Note: there is no leading underscore on name "init", though it's arguably an "internal" routine (i.e. not likely to be of use to client code).
- generate_dispatcher
-
Generate the dispatcher object, used to apply a filter's method
the stuff that does the Real Work
- apply
-
Apply applies the filter object, typically acting as a filter.
Inputs: (1) aref of input items to be operated on (2) method to use to apply filter to input items (optional) defaults to method specified inside the filter
Return: aref of output items
- save
-
Saves a copy of the filter to the using the storage_handler stored inside the object.
basic setters and getters
- name
-
Getter for object attribute name
- set_name
-
Setter for object attribute set_name
- method
-
Getter for object attribute method
- set_method
-
Setter for object attribute set_method
- description
-
Getter for object attribute description
- set_description
-
Setter for object attribute set_description
- terms
-
Getter for object attribute terms
- set_terms
-
Setter for object attribute set_terms
- modifiers
-
Getter for object attribute modifiers
- set_modifiers
-
Setter for object attribute set_modifiers
- dispatcher
-
Getter for object attribute dispatcher
- set_dispatcher
-
Setter for object attribute set_dispatcher
- storage_handler
-
Getter for object attribute storage_handler
- set_storage_handler
-
Setter for object attribute set_storage_handler
- save_filters_when_used
-
Getter for object attribute save_filters_when_used
- set_save_filters_when_used
-
Setter for object attribute set_save_filters_when_used
MOTIVATION
Why not just an href?
Why do we have List::Filter objects instead of just filter hash references? There's the usual reasoning of using abstraction to preserve flexibility (later, implementation can be changed from href to aref, qualification code might be added to the accessors, and so on).
It also makes a convenient place to ensure that a "lock_keys" has been done before the href is used (to help catch typos during development).
Why not a fixed method?
A more interesting question is why is there a "method" attribute for each filter? A more standard OOP approach to this kind of polymorphism (each filter is supposed to know it should be used) would be to simply have a class for each type of filter.
This would be inelegant for a few reasons:
(1) it would make the use of the filters more rigid. the internally specified "method" name is only the default way the filter should be applied, there are cases where you might like to deviate from it (e.g. you might invert an "omit" filter to do a "select" to check just what it is you've been skipping).
(2) it would multiply classes for no good reason, and I think it would make it a little clumsier to add new Filter "methods".
the storage handler framework (lookup/save)
Each filter can hold a pointer to it's "storage handler", which is intended to be set by the "lookup" method of that handler as the filter is returned. This gives the filter the capability to save itself later, and that's not as crazy as it sounds (not quite) because there's a path of storage locations, and the place it's read from need not be where it's saved to).
The way it works normally (?) is that the storage handler instructs the filter that when it is applied it will save a copy of itself. The storage write location is most likely going to be a yaml file that the user has access to, but the storage read location can be somewhere else (e.g. a "standard" filter, which is defined in the code, and hence not writeable). The idea here is that any filter that you've used, you get an accessible copy of, suitable for editing if you'd like to make changes.
SEE ALSO
List::Filter::Project List::Filter::Dispatcher
AUTHOR
Joseph Brenner, <doom@kzsu.stanford.edu>
COPYRIGHT AND LICENSE
Copyright (C) 2007 by Joseph Brenner
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.2 or, at your option, any later version of Perl 5 you may have available.
BUGS
None reported... yet.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 551:
You forgot a '=back' before '=head1'