• 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::FindByUID;
3
4use strict;
5use warnings;
6
7our $VERSION = '0.02';
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->{success} = 0;
25    $self->{UID_to_find} = undef;
26    $self->SUPER::_init();
27}
28
29sub searchForUID {
30    my ($self, $UID) = @_;
31    (defined($UID)) || die "Insufficient Arguments : You must provide a UID to search for";
32    $self->{UID_to_find} = $UID;
33}
34
35sub setTraversalMethod {
36	my ($self, $visitor) = @_;
37	(blessed($visitor) && $visitor->isa("Tree::Simple::Visitor"))
38		|| die "Insufficient Arguments : You must supply a valid Tree::Simple::Visitor object";
39    $self->{traversal_method} = $visitor;
40}
41
42sub visit {
43	my ($self, $tree) = @_;
44	(blessed($tree) && $tree->isa("Tree::Simple"))
45		|| die "Insufficient Arguments : You must supply a valid Tree::Simple object";
46
47    # reset our success flag
48    $self->{success} = 0;
49
50    my $UID = $self->{UID_to_find};
51    (defined($UID)) || die "Illegal Operation : You cannot search for a UID without setting one first";
52    # create our filter function
53    # NOTE:
54    # in order to get an immediate exit
55    # from the traversal once a match is
56    # found, we use 'die'. It is a somewhat
57    # unorthodox way of using this, but it
58    # works. The found tree is propogated
59    # up the call chain and returned from
60    # this function.
61	my $func;
62    if ($self->{_filter_function}) {
63        $func = sub {
64            my ($tree, $test) = @_;
65            (($tree->getUID() eq $UID) &&  $self->{_filter_function}->($tree)) && die $tree;
66            };
67    }
68    else {
69        $func = sub {
70            my ($tree, $test) = @_;
71            ($tree->getUID() eq $UID) && die $tree;
72            };
73    }
74
75    # we eval this so we can catch the tree
76    # match when it is thrown with 'die'
77    eval {
78        unless (defined($self->{traversal_method})) {
79            # include the trunk in our
80            # search if needed
81            $func->($tree) if $self->includeTrunk();
82            # and traverse
83            $tree->traverse($func);
84        }
85        else {
86            # include the trunk in our
87            # search if needed
88            $self->{traversal_method}->includeTrunk(1) if $self->includeTrunk();
89            # and visit
90            $self->{traversal_method}->setNodeFilter($func);
91            $self->{traversal_method}->visit($tree);
92        }
93    };
94    # now see what we have ...
95    if ($@) {
96        # if we caught a Tree::Simple object
97        # then we have found a match, and ...
98        if (blessed($@) && $@->isa('Tree::Simple')) {
99            # we assign it to our results
100            $self->setResults($@);
101            $self->{success} = 1;
102        }
103        # however, if it is not a Tree::Simple
104        # object then it is likely a real exception
105        else {
106            # so we re-throw it
107            die $@;
108        }
109    }
110    else {
111        # if no exception is thrown though,
112        # we failed in our search, and so we
113        # set our success flag to false
114        $self->{success} = 0;
115    }
116}
117
118sub getResult {
119    my ($self) = @_;
120    # if we did not succeed, then
121    # we return undef, ...
122    return undef unless $self->{success};
123    # otherwise we return the results
124    return $self->getResults()->[0];
125}
126
1271;
128
129__END__
130
131=head1 NAME
132
133Tree::Simple::Visitor::FindByUID - A Visitor for finding an element in a Tree::Simple hierarchy by UID
134
135=head1 SYNOPSIS
136
137  use Tree::Simple::Visitor::FindByUID;
138
139  # create a visitor object
140  my $visitor = Tree::Simple::Visitor::FindByUID->new();
141
142  # set the search path for our tree
143  $visitor->searchForUID("MyTreeUID");
144
145  # pass the visitor to a tree
146  $tree->accept($visitor);
147
148  # fetch the result, which will
149  # be the Tree::Simple object that
150  # we have found, or undefined
151  my $result = $visitor->getResult() || die "No Tree found";
152
153=head1 DESCRIPTION
154
155Given a UID and Tree::Simple hierarchy, this Visitor will attempt to find the node with the same UID.
156
157=head1 METHODS
158
159=over 4
160
161=item B<new>
162
163There are no arguments to the constructor the object will be in its default state. You can use the C<setNodeFilter>, C<setTraversalMethod>, C<includeTrunk> and C<searchForUID> methods to customize its behavior.
164
165=item B<includeTrunk ($boolean)>
166
167Based upon the value of C<$boolean>, this will tell the visitor to include the trunk of the tree in the search as well.
168
169=item B<setTraversalMethod ($visitor)>
170
171By default we will use Tree::Simple's built in depth-first (pre-order) traverse method. If however, you desire the tree to be search in a different ordering, this can be accomplished using a different traversal method, you can supply a C<$visitor> object implementing that traversal type to this method (See  B<Tree::Simple::Visitor::BreadthFirstTraversal>, B<Tree::Simple::Visitor::PreOrderTraversal> and B<Tree::Simple::Visitor::PostOrderTraversal>).
172
173=item B<searchForUID ($UID)>
174
175This is the UID we will attempt to find within the tree.
176
177=item B<setNodeFilter ($filter_function)>
178
179This 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 further check the tree nodes as they are searched and so can be used to customize search behavior. For instance, you could to check against the UID as well as some other criteria. The filter function should accept a single argument, which is the current Tree::Simple object and return either true (C<1>) on success, or false (C<0>) on failure.
180
181=item B<visit ($tree)>
182
183This 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.
184
185=item B<getResult>
186
187This method will return the tree found with the specified UID (set by the C<searchForUID> method) or C<undef> if no tree is found.
188
189=back
190
191=head1 BUGS
192
193None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it.
194
195=head1 CODE COVERAGE
196
197See the B<CODE COVERAGE> section in L<Tree::Simple::VisitorFactory> for more inforamtion.
198
199=head1 SEE ALSO
200
201These 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.
202
203=head1 ACKNOWLEDGEMENTS
204
205=over 4
206
207=item Thanks to Vitor Mori for the idea for this Visitor.
208
209=back
210
211=head1 AUTHOR
212
213stevan little, E<lt>stevan@iinteractive.comE<gt>
214
215=head1 COPYRIGHT AND LICENSE
216
217Copyright 2004, 2005 by Infinity Interactive, Inc.
218
219L<http://www.iinteractive.com>
220
221This library is free software; you can redistribute it and/or modify
222it under the same terms as Perl itself.
223
224=cut
225
226