Tree-Navigator
view release on metacpan or search on metacpan
lib/Tree/Navigator/Node.pm view on Meta::CPAN
sub child {
my ($self, $child_name) = @_;
my $child = $self->mounted_at->{$child_name}
|| $self->_child($child_name)
or die "no such child: '$child_name' in " . $self->full_path;
return $child;
}
sub _child {
my ($self, $child_name) = @_;
return undef;
}
sub children {
my $self = shift;
my $mounted = $self->mounted;
my $children = $self->_children;
return @$mounted, @$children;
}
sub content {
my $self = shift;
if (my $fh = $self->{content}) {
# if the filehandle is already present, rewind it to beginning of file
$fh->seek(0, 0);
return $fh;
}
else {
return $self->_content;
}
}
sub _content {
my $self = shift;
return undef;
}
sub content_text {
my $self = shift;
my $fh = $self->content;
return $fh ? join("", <$fh>) : "";
}
#======================================================================
# generic methods
#======================================================================
sub descendent {
my ($self, $path) = @_;
# $self is its own descendent if $path is empty
return $self if ($path // '') eq ''; # NOTE : '0' is a valid nonempty path!
# otherwise, find the child from initial path segment, and then recurse
my ($child_name, $subpath) = split m{/}, $path, 2;
my $child = $self->child($child_name)
or die "no such child: $child_name";
return $child->descendent($subpath);
}
sub is_parent { # default implementation; may be optimised in subclasses
my $self = shift;
my @children = $self->children;
return @children ? 1 : 0;
}
sub _join_path {
my ($self, $path_ini, $path_end) = @_;
$_ //= '' for $path_ini, $path_end;
return $path_ini ne '' ? $path_end ne '' ? "$path_ini/$path_end"
: $path_ini
: $path_end;
}
sub full_path {
my $self = shift;
return $self->_join_path($self->mount_point->{path}, $self->path);
}
sub last_path {
my $self = shift;
my $path = $self->full_path;
$path =~ s[^.*/][];
return $path;
}
sub subnodes_and_leaves {
my $self = shift;
my ($subnodes, $leaves)
= part {$self->child($_)->is_parent ? 0 : 1} $self->children;
$_ //= [] for $subnodes, $leaves;
return ($subnodes, $leaves);
}
#======================================================================
# WORK IN PROGRESS
#======================================================================
sub navigator {
my $self = shift;
return $self->mount_point->{navigator};
}
sub data {
my $self = shift;
my %data = (attributes => $self->attributes,
content_text => $self->content_text);
foreach my $child_name ($self->children) {
my $child = $self->child($child_name);
( run in 1.088 second using v1.01-cache-2.11-cpan-71847e10f99 )