1 2package Tree::Simple::Visitor::FromNestedHash; 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->{hash_tree} = undef; 25 $self->SUPER::_init(); 26} 27 28sub 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 39sub 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 51sub _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 701; 71 72__END__ 73 74=head1 NAME 75 76Tree::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 114Given 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 122There 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 126This 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 130This 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 142Basically 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 144The 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 150It 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 154The 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 158B<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 162This 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 168None 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 172See the B<CODE COVERAGE> section in L<Tree::Simple::VisitorFactory> for more inforamtion. 173 174=head1 SEE ALSO 175 176These 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 180stevan little, E<lt>stevan@iinteractive.comE<gt> 181 182=head1 COPYRIGHT AND LICENSE 183 184Copyright 2004, 2005 by Infinity Interactive, Inc. 185 186L<http://www.iinteractive.com> 187 188This library is free software; you can redistribute it and/or modify 189it under the same terms as Perl itself. 190 191=cut 192