NAME

Tree::MultiNode::Handle -- a cursor for navigating a Tree::MultiNode tree.

DESCRIPTION

Handle is used as a 'pointer' into the tree. It has a few attributes that it keeps track of. These are:

1. the top of the tree
2. the current node
3. the current child node
4. the depth of the current node

The top of the tree never changes, and you can reset the handle to point back at the top of the tree by calling the top() method.

The current node is where the handle is 'pointing' in the tree. The current node is changed with functions like top(), down(), and up().

The current child node is used for traversing downward into the tree. The members first(), next(), prev(), last(), and position() can be used to set the current child, and then traverse down into it.

The depth of the current node is a measure of the length of the path from the top of the tree to the current node, i.e., the top of the node has a depth of 0, each of its children has a depth of 1, etc.

Tree::MultiNode::Handle::new

Constructs a new handle. You must pass a tree object to Handle::new.

my $tree   = Tree::MultiNode->new;
my $handle = Tree::MultiNode::Handle->new($tree);

Tree::MultiNode::Handle::tree

Returns the tree that was used to construct the node. Useful if you're trying to create another node into the tree.

my $handle2 = Tree::MultiNode::Handle->new($handle->tree());

Tree::MultiNode::Handle::get_data

Retrieves both the key, and value (as an array) for the current node.

my ($key,$val) = $handle->get_data();

Tree::MultiNode::Handle::get_key

Retrieves the key for the current node.

$key = $handle->get_key();

Tree::MultiNode::Handle::set_key

Sets the key for the current node.

$handle->set_key("lname");

Tree::MultiNode::Handle::get_value

Retrieves the value for the current node.

$val = $handle->get_value();

Tree::MultiNode::Handle::set_value

Sets the value for the current node.

$handle->set_value("Wall");

Tree::MultiNode::Handle::get_child

get_child takes an optional parameter which is the position of the child that is to be retrieved. If this position is not specified, get_child attempts to return the current child. get_child returns a Node object.

my $child_node = $handle->get_child();

Tree::MultiNode::Handle::add_child

This member adds a new child node to the end of the array of children for the current node. There are three optional parameters:

- a key
- a value
- a position

If passed, the key and value will be set in the new child. If a position is passed, the new child will be inserted into the current array of children at the position specified.

$handle->add_child();                    # adds a blank child
$handle->add_child("language","perl");   # adds a child to the end
$handle->add_child("language","C++",0);  # adds a child to the front

Tree::MultiNode::Handle::add_child_node

Adds an existing node (or the top node of another tree) as a child of the current node. Works like add_child() but accepts a pre-built Tree::MultiNode::Node or Tree::MultiNode object instead of a key/value pair.

When a Tree::MultiNode (tree) object is passed, its top node is extracted and added as a child. The original tree remains valid but now shares structure with this tree -- the caller should not modify the original tree after this call.

When a position is given, the new child is inserted before the existing child at that position. Without a position, the child is appended to the end.

# append an existing node as the last child
my $node = Tree::MultiNode::Node->new("color", "red");
$handle->add_child_node($node);

# insert at a specific position
$handle->add_child_node($node, 0);   # insert as first child

# graft another tree's root node
my $other = Tree::MultiNode->new();
$handle->add_child_node($other);

Tree::MultiNode::Handle::depth

Gets the depth for the current node.

my $depth = $handle->depth();

Tree::MultiNode::Handle::select

Sets the current child via a specified value -- basically it iterates through the array of children, looking for a match. You have to supply the key to look for, and optionally a sub ref to find it. The default for this sub is

sub { return shift eq shift; }

Which is sufficient for testing the equality of strings (the most common thing that I think will get stored in the tree). If you're storing multiple data types as keys, you'll have to write a sub that figures out how to perform the comparisons in a sane manner.

The code reference should take two arguments, and compare them -- return false if they don't match, and true if they do.

$handle->select('lname', sub { return shift eq shift; } );

Tree::MultiNode::Handle::position

Sets, or retrieves the current child position.

print "curr child pos is: ", $handle->position(), "\n";
$handle->position(5);    # sets the 6th child as the current child

Tree::MultiNode::Handle::first Tree::MultiNode::Handle::next Tree::MultiNode::Handle::prev Tree::MultiNode::Handle::last

These functions manipulate the current child member. first() sets the first child as the current child, while last() sets the last. next(), and prev() will move to the next/prev child respectively. If there is no current child node, next() will have the same effect as first(), and prev() will operate as last(). prev() fails if the current child is the first child, and next() fails if the current child is the last child -- i.e., they do not wrap around.

These functions will fail if there are no children for the current node.

$handle->first();  # sets to the 0th child
$handle->next();   # to the 1st child
$handle->prev();   # back to the 0th child
$handle->last();   # go straight to the last child.

Tree::MultiNode::Handle::down

down() moves the handle to point at the current child node. It fails if there is no current child node. When down() is called, the current child becomes invalid (undef).

$handle->down();

Tree::MultiNode::Handle::up

up() moves the handle to point at the parent of the current node. It fails if there is no parent node. When up() is called, the current child becomes invalid (undef).

$handle->up();

Tree::MultiNode::Handle::top

Resets the handle to point back at the top of the tree. When top() is called, the current child becomes invalid (undef).

$handle->top();

Tree::MultiNode::Handle::children

This returns an array of Node objects that represents the children of the current Node. Unlike Node::children(), the array Handle::children() is not a reference to an array, but an array. Useful if you need to iterate through the children of the current node.

print "There are: ", scalar($handle->children()), " children\n";
foreach $child ($handle->children()) {
  print $child->key(), " : ", $child->value(), "\n";
}

Tree::MultiNode::Handle::num_children

Returns the number of children for the current node. This is more efficient than scalar($handle->children()) because it does not copy the children array.

my $count = $handle->num_children();

Tree::MultiNode::Handle::child_key_positions

This function returns a hash table that consists of the child keys as the hash keys, and the position in the child array as the value. This allows for a quick and dirty way of looking up the position of a given key in the child list.

my %h = $handle->child_key_positions();

Tree::MultiNode::Handle::get_child_key

Returns the key at the specified position, or from the corresponding child node.

my $key = $handle->get_child_key();

Tree::MultiNode::Handle::get_child_value

Returns the value at the specified position, or from the corresponding child node.

my $value = $handle->get_child_value();

Tree::MultiNode::Handle::kv_pairs

Returns Tree::MultiNode::Node::child_kv_pairs() for the current node for this handle.

my %pairs = $handle->kv_pairs();

Tree::MultiNode::Handle::remove_child

Removes the child at the specified position, or at the current child position if no position is given. Returns the key and value of the removed child node.

my ($key, $value) = $handle->remove_child(0);

Tree::MultiNode::Handle::child_keys

Returns the keys from the current node's children. Returns undef if there is no current node.

Tree::MultiNode::Handle::child_values

Returns the values from the current node's children. Returns undef if there is no current node.

Tree::MultiNode::Handle::traverse

$handle->traverse(sub {
  my $h = pop;
  printf "%sk: %s v: %s\n",('  ' x $handle->depth()),$h->get_data();
});

Traverse takes a subroutine reference, and will visit each node of the tree, starting with the node the handle currently points to, recursively down from the current position of the handle. Each time the subroutine is called, it will be passed a handle which points to the node to be visited. Any additional arguments after the sub ref will be passed to the traverse function _before_ the handle is passed. This should allow you to pass constant arguments to the sub ref.

Modifying the node that the handle points to will cause traverse to work from the new node forward.

Tree::MultiNode::Handle::otraverse

Like traverse(), but designed for passing an object method. The first argument after the handle should be the object, the second should be the method name or code reference, followed by any additional arguments. The handle is passed as the last argument to the method.

This allows you to have the subref be a method on an object (and still pass the object's 'self' to the method).

$handle->otraverse( $obj, \&Some::Object::method, $const1, \%const2 );

...
sub method
{
  my $handle = pop;
  my $self   = shift;
  my $const1 = shift;
  my $const2 = shift;
  # do something
}