|
Tree::Numbered - a thin N-ary tree structure with a unique number for each item. |
Tree::Numbered - a thin N-ary tree structure with a unique number for each item.
use Tree::Numbered;
my $tree = Tree::Numbered->new('John Doe');
$tree->append('John Doe Jr.');
$tree->append('Marry-Jane Doe');
while (my $branch = $tree->nextNode) {
$branch->delete if ($branch->getValue eq 'Stuff I dont want');
}
my $itemId = what_the_DB_says; print join ' --- ', $tree->follow($itemId); # a list of items up to itemId.
$tree->allProcess( sub {
my $self = shift;
$self->getValue =~ /^(\S*)/;
$self->addField('FirstName', $1);
} );
etc.
Tree::Numbered is a special N-ary tree with a number for each node. This is useful on many occasions. The first use I found for that (and wrote this for) was to store information about the selected item as a number instead of storing the whole value which is space-expensive.
Every tree also has a lucky number of his own that distinguishes it from other trees created by the same module. This module is thin on purpose and is meant to be a base class for stuff that can make use of this behaveiour. For example, I wrote Tree::Numbered::DB which ties a tree to a table in a database, and Javascript::Menu which uses this tree to build menus for websites.
One more feature that the module implements for the ease of subclassing it is an API for adding and removing fields from trees and nodes.
There are two forms of calling new. The first is calling it with one argument only - the value for the node. If you do that, the tree / node will be created with one field, called 'Value', and this field will receive the value you supplied as an argument.
The second form is calling new with a hash of <field name> => <field value> pairs. For each pair, a field by the name <field name> be created, and it's value will be <field value>. The Value field will not be created unless you specifically request it.
Note: Calling new with no arguments is the same as calling it in the second form.
As this module is designed for subclassing, I added a mechanism to easily create fields in a tree. Fields are different from normal object attributes in that they are specifically registered as fields within their object, and can be added, removed, and querried for existence. For every field a set of accessors is auto created (actually, autoloaded). In the section 'Subclassing Issues' there's more on using fields vs. regular attributes.
One more important thing to know about fields is that every node inherits all fields that his parent had at the moment of creation. The value of the field is also inherited unless the field was requested in the argument list for append, in which case it takes the value provided as an argument.
Naming your fields: If you want to make use of the automatic accessors, you might want to name your fields with a capital first letter. This is because the accessors created for a field are nothing more then the name of the field prefixed with either 'get' or 'set'. Alternatively, use underscore-lower letter if that's your style.
No problem - The module knows of a default field called 'Value' which is created if you only give one argument - the value - to new or append. When you build a tree like that, you'll have the methods getValue and setValue. Furthermore, the method follow guesses that you want this field if you do not specify any other. So working with one field only is just a short-code version of working with many.
If you need to add a field to all existing descendants of a node (future ones inherit the field automatically) use either deepProcess or allProcess as described above in 'Synopsys'.
Returns: True on success, undef on failure.
removeField(name)Returns: True on success, undef on failure.
getField(name)
Every node in the tree has its own cursor that points to the current item. When you start iterating, the cursor is placed just before the first child. When you are at the last item, trying to move beyond the last item will put the cursor after the last item (which will result in an undef value, signalling the end) but the next attempt will cause the cursor to start over from the first child.
The following accessors are always available and deal with the node's properties, not with fields:
Also, as described above, for each field you create, a getter and a setter automatically show up when needed. For each field *, you'll have the methods get* and set*.
Well, I didn't include the node numbers just for fun, this is actually very needed sometimes. There are three basic service methods that use this (subclasses may add to this):
getSubTree([number])listChildNumbers([number])
There are two methods that apply a certain subroutine to whole trees:
For example, if you implement a property using the fields mechanism, and you don't want the user to access it, you'll have to manually override the automatic accessors to die or do something unpleasant when they're used.
Secondly, if you register a property as a field - it is easy to remove it by accident even if you count on it to always exist. That's bad, isn't it?
And lastly, if you count on a value to be frequently used, you might not want the overhead of autoloading the accessors or you don't need it in the list of fields.
The benefits of using fields, are in the easiness of managing a set of fields acording to changing demands and the simplicity of extending the behaveiour of a class. For example, check out my Javascript::Menu which creates the URL field if the user is just trying to build a navigational menu, but doesn't bother if the user uses the more complex, action based menus that I designed the module for.
If you do want to change the behaveiour, I assume that you know what you're doing and that you have read some source. Then you'll have no problem with implementing your desired behaveiour.
Works pretty well for me. If you found anything, please send a bug report: <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Tree-Numbered> or send mail to <bug-Tree-Numbered#rt.cpan.org>
Tree::Numbered::DB, Javascript::Menu
Yosef Meller, < mellerf@netvision.net.il >
Copyright 2003 by Yosef Meller
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
Tree::Numbered - a thin N-ary tree structure with a unique number for each item. |