Commit | Line | Data |
3fea05b9 |
1 | |
2 | package Tree::Simple::Visitor::FromNestedHash; |
3 | |
4 | use strict; |
5 | use warnings; |
6 | |
7 | our $VERSION = '0.03'; |
8 | |
9 | use Scalar::Util qw(blessed); |
10 | |
11 | use base qw(Tree::Simple::Visitor); |
12 | |
13 | sub 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 | |
22 | sub _init { |
23 | my ($self) = @_; |
24 | $self->{hash_tree} = undef; |
25 | $self->SUPER::_init(); |
26 | } |
27 | |
28 | sub setHashTree { |
29 | my ($self, $hash_tree) = @_; |
30 | (defined($hash_tree) && ref($hash_tree) eq 'HASH') |
31 | || die "Insufficient Arguments : You must supply a valid HASH reference"; |
32 | # validate the tree ... |
33 | # it must not be empty |
34 | (scalar keys %{$hash_tree} == 1) |
35 | || die "Insufficient Arguments : The hash tree provided must be a single rooted tree"; |
36 | $self->{hash_tree} = $hash_tree; |
37 | } |
38 | |
39 | sub visit { |
40 | my ($self, $tree) = @_; |
41 | (blessed($tree) && $tree->isa("Tree::Simple")) |
42 | || die "Insufficient Arguments : You must supply a valid Tree::Simple object"; |
43 | $self->_buildTree( |
44 | $tree, |
45 | $self->{hash_tree}, |
46 | $self->getNodeFilter(), |
47 | $self->includeTrunk() |
48 | ); |
49 | } |
50 | |
51 | sub _buildTree { |
52 | my ($self, $tree, $hash, $node_filter, $include_trunk) = @_; |
53 | foreach my $key (sort keys %{$hash}) { |
54 | my $node = $key; |
55 | $node = $node_filter->($node) if $node_filter; |
56 | my $new_tree; |
57 | if ($include_trunk) { |
58 | $tree->setNodeValue($node); |
59 | $new_tree = $tree; |
60 | } |
61 | else { |
62 | $new_tree = Tree::Simple->new($node); |
63 | $tree->addChild($new_tree); |
64 | } |
65 | $self->_buildTree($new_tree, $hash->{$key}, $node_filter) |
66 | if ref($hash->{$key}) eq 'HASH'; |
67 | } |
68 | } |
69 | |
70 | 1; |
71 | |
72 | __END__ |
73 | |
74 | =head1 NAME |
75 | |
76 | Tree::Simple::Visitor::FromNestedHash - A Visitor for creating Tree::Simple objects from nested hash trees. |
77 | |
78 | =head1 SYNOPSIS |
79 | |
80 | use Tree::Simple::Visitor::FromNestedHash; |
81 | |
82 | my $visitor = Tree::Simple::Visitor::FromNestedHash->new(); |
83 | |
84 | # given this nested hash tree |
85 | my $hash_tree = { |
86 | Root => { |
87 | Child1 => { |
88 | GrandChild1 => {}, |
89 | GrandChild2 => {} |
90 | }, |
91 | Child2 => {} |
92 | } |
93 | }; |
94 | |
95 | # set the array tree we |
96 | # are going to convert |
97 | $visitor->setHashTree($hash_tree); |
98 | |
99 | $tree->accept($visitor); |
100 | |
101 | # this then creates the equivalent Tree::Simple object: |
102 | # Tree::Simple->new("Root") |
103 | # ->addChildren( |
104 | # Tree::Simple->new("Child1") |
105 | # ->addChildren( |
106 | # Tree::Simple->new("GrandChild1"), |
107 | # Tree::Simple->new("GrandChild2") |
108 | # ), |
109 | # Tree::Simple->new("Child2"), |
110 | # ); |
111 | |
112 | =head1 DESCRIPTION |
113 | |
114 | Given a tree constructed from nested hashs, this Visitor will create the equivalent Tree::Simple heirarchy. |
115 | |
116 | =head1 METHODS |
117 | |
118 | =over 4 |
119 | |
120 | =item B<new> |
121 | |
122 | There are no arguments to the constructor the object will be in its default state. You can use the C<setNodeFilter> methods to customize its behavior. |
123 | |
124 | =item B<setNodeFilter ($filter_function)> |
125 | |
126 | 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 created, the C<$filter_function> is passed the node value extracted from the hash prior to it being inserted into the tree being built. The C<$filter_function> is expected to return the value desired for inclusion into the tree. |
127 | |
128 | =item B<setHashTree ($hash_tree)> |
129 | |
130 | This method is used to set the C<$hash_tree> that our Tree::Simple heirarchy will be constructed from. It must be in the following form: |
131 | |
132 | { |
133 | Root => { |
134 | Child1 => { |
135 | GrandChild1 => {}, |
136 | GrandChild2 => {} |
137 | }, |
138 | Child2 => {} |
139 | } |
140 | } |
141 | |
142 | Basically each key in the hash is considered a node, values are ignored unless it is a hash reference with at least one key in it, in which case it is interpreted as containing the children of the node created from the key. |
143 | |
144 | The tree is validated prior being accepted, if it fails validation an execption will be thrown. The rules are as follows; |
145 | |
146 | =over 4 |
147 | |
148 | =item The hash tree must not be empty. |
149 | |
150 | It makes not sense to create a tree out of nothing, so it is assumed that this is a sign of something wrong. |
151 | |
152 | =item The hash tree must be a single rooted tree. |
153 | |
154 | The hash tree should have only one key in it's first level, if it has more than one, then it is not a single rooted tree. |
155 | |
156 | =back |
157 | |
158 | B<NOTE:> Hash keys are sorted ascii-betically before being added to the tree, this results in a somewhat more predictable hierarchy. |
159 | |
160 | =item B<visit ($tree)> |
161 | |
162 | 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. |
163 | |
164 | =back |
165 | |
166 | =head1 BUGS |
167 | |
168 | None that I am aware of. Of course, if you find a bug, let me know, and I will be sure to fix it. |
169 | |
170 | =head1 CODE COVERAGE |
171 | |
172 | See the B<CODE COVERAGE> section in L<Tree::Simple::VisitorFactory> for more inforamtion. |
173 | |
174 | =head1 SEE ALSO |
175 | |
176 | 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. |
177 | |
178 | =head1 AUTHOR |
179 | |
180 | stevan little, E<lt>stevan@iinteractive.comE<gt> |
181 | |
182 | =head1 COPYRIGHT AND LICENSE |
183 | |
184 | Copyright 2004, 2005 by Infinity Interactive, Inc. |
185 | |
186 | L<http://www.iinteractive.com> |
187 | |
188 | This library is free software; you can redistribute it and/or modify |
189 | it under the same terms as Perl itself. |
190 | |
191 | =cut |