Mercurial > pub > Impl
diff Lib/IMPL/DOM/Node.pm @ 18:818c74b038ae
DOM Schema + tests
author | Sergey |
---|---|
date | Thu, 10 Sep 2009 17:42:47 +0400 |
parents | 75d55f4ee263 |
children | fafe56cfcd69 |
line wrap: on
line diff
--- a/Lib/IMPL/DOM/Node.pm Wed Sep 09 17:43:31 2009 +0400 +++ b/Lib/IMPL/DOM/Node.pm Thu Sep 10 17:42:47 2009 +0400 @@ -17,13 +17,15 @@ public _direct property nodeValue => prop_all; public _direct property childNodes => { get => \&_getChildNodes }; public _direct property parentNode => prop_get ; - private _direct property _propertyMap => prop_get ; + public _direct property rootNode => { get => \&_getRootNode}; + private _direct property _propertyMap => prop_all ; } sub CTOR { my ($this,%args) = @_; $this->nodeName($args{nodeName}) or die new IMPL::InvalidArgumentException("A name is required"); + $this->nodeValue($args{nodeValue}); } sub insertNode { @@ -47,7 +49,8 @@ $node->{$parentNode}->removeNode($node) if ($node->{$parentNode}); - $this->childNodes->Append($node); + my $children = $this->childNodes; + $children->Append($node); $node->_setParent( $this ); @@ -73,7 +76,7 @@ my ($this) = @_; $this->{$childNodes} = new IMPL::Object::List() unless $this->{$childNodes}; - $this->{$childNodes}; + return $this->{$childNodes}; } sub removeNode { @@ -81,8 +84,8 @@ if ($this == $node->{$parentNode}) { $this->childNodes->RemoveItem($node); - $node->{$parentNode} = undef; - return $this; + $node->_setParent(undef); + return $node; } else { die new IMPL::InvalidOperationException("The specified node isn't belong to this node"); } @@ -101,11 +104,11 @@ # replace (or set) old node $this->childNodes->[$index] = $node; - # save new parent + # set new parent $node->_setParent( $this ); # unlink old node if we have one - $nodeOld->{$parentNode} = undef if $nodeOld; + $nodeOld->_setParent(undef) if $nodeOld; # return old node return $nodeOld; @@ -115,21 +118,64 @@ my ($this,$pos) = @_; if ( my $node = $this->childNodes->RemoveAt($pos) ) { - $node->{$parentNode} = undef; + $node->_setParent(undef); + return $node; + } else { + return undef; + } +} + +sub removeLast { + my ($this) = @_; + + if ( my $node = $this->{$childNodes} ? $this->{$childNodes}->RemoveLast() : undef) { + $node->_setParent(undef); return $node; } else { return undef; } } +sub removeSelected { + my ($this,$query) = @_; + + my @newSet; + my @result; + + if (ref $query eq 'CODE') { + &$query($_) ? push @result, $_ : push @newSet, $_ foreach @{$this->childNodes}; + } elsif (defined $query) { + $_->nodeName eq $query ? push @result, $_ : push @newSet, $_ foreach @{$this->childNodes}; + } else { + my $children = $this->childNodes; + $_->_setParent(undef) foreach @$children; + delete $this->{$childNodes}; + return wantarray ? @$children : $children; + } + + $_->_setParent(undef) foreach @result; + + $this->{$childNodes} = @newSet ? bless \@newSet ,'IMPL::Object::List' : undef; + + return wantarray ? @result : \@result; +} + sub selectNodes { my ($this,$query) = @_; + my @result; if (ref $query eq 'CODE') { @result = grep &$query($_), @{$this->childNodes}; + } elsif (defined $query) { + @result = grep $_->nodeName eq $query, @{$this->childNodes}; } else { - @result = grep $_->nodeName eq $query, @{$this->childNodes}; + if (wantarray) { + return @{$this->childNodes}; + } else { + @result = $this->childNodes; + return \@result; + } } return wantarray ? @result : \@result; @@ -143,18 +189,49 @@ $_[0]->childNodes->Count ? 1 : 0; } +sub _getRootNode { + $_[0]->{$rootNode} || $_[0]; +} + +sub _updateRootRefs { + my ($this) = @_; + + if ( my $newRoot = $this->{$parentNode} ? $this->{$parentNode}->rootNode : undef) { + if ($this->{$rootNode} ? $this->{$rootNode} != $newRoot : 1 ) { + $this->{$rootNode} = $newRoot; + weaken($this->{$rootNode}); + if ($this->{$childNodes}) { + $_->_updateRootRefs foreach @{$this->{$childNodes}}; + } + } + } elsif($this->{$rootNode}) { + delete $this->{$rootNode}; + if ($this->{$childNodes}) { + $_->_updateRootRefs foreach @{$this->{$childNodes}}; + } + } +} + sub _setParent { my ($this,$node) = @_; - $this->{$parentNode} = $node; - # prevent from creating cyclicreferences - weaken($this->{$parentNode}); + + if (($node || 0) != ($this->{$parentNode} || 0)) { + if ($node) { + $this->{$parentNode} = $node; + # prevent from creating cyclicreferences + weaken($this->{$parentNode}); + } else { + delete $this->{$parentNode}; + } + $this->_updateRootRefs; + } } sub text { my ($this) = @_; - join '', $this->nodeValue, map $_->nodeValue, @{$this->childNodes}; + join '', $this->nodeValue || '', map $_->nodeValue || '', @{$this->childNodes}; } sub Property {