• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/CPANInternal-159.1/Tree-Simple-VisitorFactory-0.10/lib/Tree/Simple/Visitor/
1
2package Tree::Simple::Visitor::FindByPath;
3
4use strict;
5use warnings;
6
7our $VERSION = '0.03';
8
9use Scalar::Util qw(blessed);
10
11use base qw(Tree::Simple::Visitor);
12
13sub new {
14    my ($_class) = @_;
15    my $class = ref($_class) || $_class;
16    my $visitor = {};
17    bless($visitor, $class);
18    $visitor->_init();
19    return $visitor;
20}
21
22sub _init {
23    my ($self) = @_;
24    $self->{search_path} = undef;
25    $self->{success} = 0;
26    $self->SUPER::_init();
27}
28
29sub setSearchPath {
30    my ($self, @path) = @_;
31    (@path) || die "Insufficient Arguments : You must specify a path";
32    $self->{search_path} = \@path;
33}
34
35sub visit {
36	my ($self, $tree) = @_;
37	(blessed($tree) && $tree->isa("Tree::Simple"))
38		|| die "Insufficient Arguments : You must supply a valid Tree::Simple object";
39
40    # reset our success flag
41    $self->{success} = 0;
42
43    # get our filter function
44	my $func;
45    if ($self->{_filter_function}) {
46        $func = sub {
47            my ($tree, $test) = @_;
48            return (($self->{_filter_function}->($tree) . "") eq $test);
49            };
50    }
51    else {
52        $func = sub {
53            my ($tree, $test) = @_;
54            return (($tree->getNodeValue() . "") eq $test);
55            };
56    }
57
58    # get ready with our results
59    my @results;
60
61    # get our path
62    my @path = @{$self->{search_path}};
63
64    # get our variables ready
65    my $current_path;
66    my $current_tree = $tree;
67
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
76        shift @path;
77    }
78
79    TOP: {
80        # if we have no more @path we have found it
81        unless (@path) {
82            # store the current tree as
83            # our last result
84            $self->setResults(@results, $current_tree);
85            # and set the sucess flag
86            $self->{success} = 1;
87            return;
88        }
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
93        # for a match
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
98                # in our results, and
99                push @results => $current_tree;
100                # we change our current tree
101                $current_tree = $child;
102                # and go back to the TOP
103                goto TOP;
104            }
105        }
106
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;
112    }
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);
118}
119
120sub getResult {
121    my ($self) = @_;
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];
128}
129
1301;
131
132__END__
133
134=head1 NAME
135
136Tree::Simple::Visitor::FindByPath - A Visitor for finding an element in a Tree::Simple hierarchy with a path
137
138=head1 SYNOPSIS
139
140  use Tree::Simple::Visitor::FindByPath;
141
142  # create a visitor object
143  my $visitor = Tree::Simple::Visitor::FindByPath->new();
144
145  # set the search path for our tree
146  $visitor->setSearchPath(qw(1 1.2 1.2.2));
147
148  # pass the visitor to a tree
149  $tree->accept($visitor);
150
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";
155
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
159
160=head1 DESCRIPTION
161
162Given a path and Tree::Simple hierarchy, this Visitor will attempt to find the node specified by the path.
163
164=head1 METHODS
165
166=over 4
167
168=item B<new>
169
170There 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.
171
172=item B<includeTrunk ($boolean)>
173
174Based upon the value of C<$boolean>, this will tell the visitor to include the trunk of the tree in the search as well.
175
176=item B<setSearchPath (@path)>
177
178This 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).
179
180=item B<setNodeFilter ($filter_function)>
181
182This 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.
183
184=item B<visit ($tree)>
185
186This 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.
187
188=item B<getResult>
189
190This method will return the tree found at the specified path (set by the C<setSearchPath> method) or C<undef> if no tree is found.
191
192=item B<getResults>
193
194This 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.
195
196=back
197
198=head1 BUGS
199
200None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
201
202=head1 CODE COVERAGE
203
204See the B<CODE COVERAGE> section in L<Tree::Simple::VisitorFactory> for more inforamtion.
205
206=head1 SEE ALSO
207
208These 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.
209
210=head1 AUTHOR
211
212stevan little, E<lt>stevan@iinteractive.comE<gt>
213
214=head1 COPYRIGHT AND LICENSE
215
216Copyright 2004, 2005 by Infinity Interactive, Inc.
217
218L<http://www.iinteractive.com>
219
220This library is free software; you can redistribute it and/or modify
221it under the same terms as Perl itself.
222
223=cut
224
225