Data-Hierarchy
view release on metacpan or search on metacpan
Hierarchy.pm view on Meta::CPAN
for my $subpath (@datapoints) {
my $matched = 1;
for (keys %$prop_regexps) {
my $lookat = (index($_, '.') == 0) ?
$self->{sticky}{$subpath} : $self->{hash}{$subpath};
$matched = 0
unless exists $lookat->{$_}
&& $lookat->{$_} =~ m/$prop_regexps->{$_}/;
last unless $matched;
}
push @items, $subpath
if $matched;
}
return @items;
}
=item C<merge $other_hierarchy, $path>
Given a second L<Data::Hierarchy> object and a path, copies all the
properties from the other object at C<$path> or below into the
corresponding paths in the object this method is invoked on. All
properties from the object this is invoked on at C<$path> or below are
erased first.
=cut
sub merge {
my ($self, $other, $path) = @_;
$self->_path_safe ($path);
my %datapoints = map {$_ => 1} ($self->_all_descendents ($path),
$other->_all_descendents ($path));
for my $datapoint (sort keys %datapoints) {
my $my_props = $self->get ($datapoint, 1);
my $other_props = $other->get ($datapoint);
for (keys %$my_props) {
$other_props->{$_} = undef
unless defined $other_props->{$_};
}
$self->_store_no_cleanup ($datapoint, $other_props);
}
$self->_remove_redundant_properties_and_undefs;
}
=item C<to_relative $base_path>
Given a path which B<every> element of the hierarchy must be contained
in, returns a special Data::Hierarchy::Relative object which
represents the hierarchy relative that path. The B<only> thing you can
do with a Data::Hierarchy::Relative object is call
C<to_absolute($new_base_path)> on it, which returns a new
L<Data::Hierarchy> object at that base path. For example, if
everything in the hierarchy is rooted at C</home/super_project> and it
needs to be moved to C</home/awesome_project>, you can do
$hierarchy = $hierarchy->to_relative('/home/super_project')->to_absolute('/home/awesome_project');
(Data::Hierarchy::Relative objects may be a more convenient
serialization format than Data::Hierarchy objects, if they are
tracking the state of some relocatable resource.)
=cut
sub to_relative {
my $self = shift;
my $base_path = shift;
return Data::Hierarchy::Relative->new($base_path, %$self);
}
# Internal method.
#
# Dies if the given path has a trailing slash and is not the root. If it is root,
# destructively changes the path given as argument to the empty string.
sub _path_safe {
# Have to do this explicitly on the elements of @_ in order to be destructive
if ($_[1] eq $_[0]->{sep}) {
$_[1] = '';
return;
}
my $self = shift;
my $path = shift;
my $location_of_last_separator = rindex($path, $self->{sep});
return if $location_of_last_separator == -1;
my $potential_location_of_trailing_separator = (length $path) - (length $self->{sep});
return unless $location_of_last_separator == $potential_location_of_trailing_separator;
require Carp;
Carp::confess('non-root path has a trailing slash!');
}
# Internal method.
#
# Actually does property updates (to hash or sticky, depending on name).
sub _store {
my ($self, $path, $new_props) = @_;
my $old_props = exists $self->{hash}{$path} ? $self->{hash}{$path} : undef;
my $merged_props = {%{$old_props||{}}, %$new_props};
for (keys %$merged_props) {
if (index($_, '.') == 0) {
defined $merged_props->{$_} ?
$self->{sticky}{$path}{$_} = $merged_props->{$_} :
delete $self->{sticky}{$path}{$_};
delete $merged_props->{$_};
}
else {
delete $merged_props->{$_}
unless defined $merged_props->{$_};
}
}
$self->{hash}{$path} = $merged_props;
}
( run in 0.872 second using v1.01-cache-2.11-cpan-71847e10f99 )