2 package Tree::Simple::Visitor::FindByPath;
9 use Scalar::Util qw(blessed);
11 use base qw(Tree::Simple::Visitor);
15 my $class = ref($_class) || $_class;
17 bless($visitor, $class);
24 $self->{search_path} = undef;
26 $self->SUPER::_init();
30 my ($self, @path) = @_;
31 (@path) || die "Insufficient Arguments : You must specify a path";
32 $self->{search_path} = \@path;
36 my ($self, $tree) = @_;
37 (blessed($tree) && $tree->isa("Tree::Simple"))
38 || die "Insufficient Arguments : You must supply a valid Tree::Simple object";
40 # reset our success flag
43 # get our filter function
45 if ($self->{_filter_function}) {
47 my ($tree, $test) = @_;
48 return (($self->{_filter_function}->($tree) . "") eq $test);
53 my ($tree, $test) = @_;
54 return (($tree->getNodeValue() . "") eq $test);
58 # get ready with our results
62 my @path = @{$self->{search_path}};
64 # get our variables ready
66 my $current_tree = $tree;
68 # check to see if we have been
69 # asked to include the trunk
70 if ($self->includeTrunk()) {
71 # if we dont match the root of the path
72 # then we have failed already and so return
73 $self->setResults(()) && return
74 unless $func->($current_tree, $path[0]);
75 # if we do match, then remove it off the path
80 # if we have no more @path we have found it
82 # store the current tree as
84 $self->setResults(@results, $current_tree);
85 # and set the sucess flag
89 # otherwise we need to keep looking ...
90 # get the next element in the path
91 $current_path = shift @path;
92 # now check all the current tree's children
94 foreach my $child ($current_tree->getAllChildren()) {
95 if ($func->($child, $current_path)) {
96 # if we find a match, then
97 # we store the current tree
99 push @results => $current_tree;
100 # we change our current tree
101 $current_tree = $child;
102 # and go back to the TOP
107 # if we do not find a match, then we can fall off
108 # this block and the whole subroutine for that matter
109 # since we know the match has failed.
110 push @results => $current_tree
111 if (@path || $self->{success} == 0) && $current_tree != $tree;
113 # we do however, store the
114 # results as far as we got,
115 # so that the user can maybe
116 # do something else to recover
117 $self->setResults(@results);
122 # if we did not succeed, then
123 # we return undef, ...
124 return undef unless $self->{success};
125 # otherwise we return the
126 # last in the results
127 return $self->getResults()->[-1];
136 Tree::Simple::Visitor::FindByPath - A Visitor for finding an element in a Tree::Simple hierarchy with a path
140 use Tree::Simple::Visitor::FindByPath;
142 # create a visitor object
143 my $visitor = Tree::Simple::Visitor::FindByPath->new();
145 # set the search path for our tree
146 $visitor->setSearchPath(qw(1 1.2 1.2.2));
148 # pass the visitor to a tree
149 $tree->accept($visitor);
151 # fetch the result, which will
152 # be the Tree::Simple object that
153 # we have found, or undefined
154 my $result = $visitor->getResult() || die "No Tree found";
156 # our result's node value should match
157 # the last element in our path
158 print $result->getNodeValue(); # this should print 1.2.2
162 Given a path and Tree::Simple hierarchy, this Visitor will attempt to find the node specified by the path.
170 There are no arguments to the constructor the object will be in its default state. You can use the C<setSearchPath> and C<setNodeFilter> methods to customize its behavior.
172 =item B<includeTrunk ($boolean)>
174 Based upon the value of C<$boolean>, this will tell the visitor to include the trunk of the tree in the search as well.
176 =item B<setSearchPath (@path)>
178 This is the path we will attempt to follow down the tree. We will do a stringified comparison of each element of the path and the current tree's node (or the value returned by the node filter if it is set).
180 =item B<setNodeFilter ($filter_function)>
182 This method accepts a CODE reference as its C<$filter_function> argument and throws an exception if it is not a code reference. This code reference is used to filter the tree nodes as they are collected. This can be used to customize output, or to gather specific information from a more complex tree node. The filter function should accept a single argument, which is the current Tree::Simple object.
184 =item B<visit ($tree)>
186 This is the method that is used by Tree::Simple's C<accept> method. It can also be used on its own, it requires the C<$tree> argument to be a Tree::Simple object (or derived from a Tree::Simple object), and will throw and exception otherwise.
190 This method will return the tree found at the specified path (set by the C<setSearchPath> method) or C<undef> if no tree is found.
194 This method will return the tree's that make up the path specified in C<setSearchPath>. In the case of a failed search, this can be used to find the elements which did successfully match along the way.
200 None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
204 See the B<CODE COVERAGE> section in L<Tree::Simple::VisitorFactory> for more inforamtion.
208 These Visitor classes are all subclasses of B<Tree::Simple::Visitor>, which can be found in the B<Tree::Simple> module, you should refer to that module for more information.
212 stevan little, E<lt>stevan@iinteractive.comE<gt>
214 =head1 COPYRIGHT AND LICENSE
216 Copyright 2004, 2005 by Infinity Interactive, Inc.
218 L<http://www.iinteractive.com>
220 This library is free software; you can redistribute it and/or modify
221 it under the same terms as Perl itself.