# $Id$
use strict;
use warnings;
package minitree;
{ my( @parent, @next_sibling, @previous_sibling, @first_child, @name, @value, @attributes, @pos);
my $last_obj=0;
sub new
{ my $class= shift;
my $att_class= shift;
my %attributes= @_;
$last_obj++;
my $id= $last_obj;
my $self= bless \$id, $class;
$self->name( $attributes{name}); delete $attributes{name};
$self->value( $attributes{value}); delete $attributes{value};
my @node_attributes= map { $att_class->new( $self, $_ => $attributes{$_}) } sort keys %attributes;
$self->attributes( \@node_attributes);
return $self;
}
BEGIN
{ foreach my $method ( qw( parent next_sibling previous_sibling first_child name value pos) )
{ no strict 'refs';
*{$method}= sub { my $self= shift;
if( @_) { ${$method}[$$self]= shift; }
return ${$method}[$$self];
};
}
}
sub attributes
{ my $self= shift;
if( @_) { $attributes[$$self]= shift; }
return $attributes[$$self] || [];
};
sub root { my $self= shift; while( $self->parent) { $self= $self->parent; } return $self; }
sub last_child
{ my $self= shift;
my $child= $self->first_child || return;
while( $child->next_sibling) { $child= $child->next_sibling; }
return $child;
}
sub children
{ my $self= shift;
my @children;
my $child= $self->first_child || return;
while( $child) { push @children, $child; $child= $child->next_sibling; }
return @children;
}
sub add_as_last_child_of
{ my( $child, $parent)= @_;
$child->parent( $parent);
if( my $previous_sibling= $parent->last_child)
{ $previous_sibling->next_sibling( $child);
$child->previous_sibling( $previous_sibling);
}
else
{ $parent->first_child( $child); }
}
sub set_pos
{ my $self= shift;
my $pos = shift || 1;
$self->pos( $pos++);
foreach my $att (@{$self->attributes})
{ $att->pos( $pos++); }
foreach my $child ($self->children)
{ $pos= $child->set_pos( $pos); }
return $pos;
}
sub dump
{ my $self= shift;
return "$$self : "
# . join ( " - ", grep { $_ } map { "$_ : " . ${$self->$_} if( $self->$_) }
# qw( parent next_sibling previous_sibling first_child)
# )
# . ' : '
. join ( " - ", map { "$_ : " . $self->$_ } qw( name value pos))
. " : " . join( " - ", map { $_->dump } @{$self->attributes})
;
}
sub dump_all
{ my $class= shift;
foreach my $id (1..$last_obj)
{ my $self= bless \$id, $class;
print $self->dump, "\n";
}
}
}
1;
package attribute;
{
my( @name, @value, @parent, @pos);
my $last_obj=0;
sub new
{ my( $class, $parent, $name, $value)= @_;
my $id= $last_obj++;
my $self= bless \$id, $class;
$self->name( $name );
$self->value( $value );
$self->parent( $parent);
return $self;
}
BEGIN
{ foreach my $method ( qw( parent name value pos) )
{ no strict 'refs';
*{$method}= sub { my $self= shift;
if( @_) { ${$method}[$$self]= shift; }
return ${$method}[$$self];
};
}
}
sub dump { my $self= shift; return $self->name . " => " . $self->value . " (" . $self->pos . ")"; }
}
1;