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