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