Mercurial > pub > Impl
annotate Lib/IMPL/DOM/Node.pm @ 16:75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
| author | Sergey |
|---|---|
| date | Tue, 08 Sep 2009 17:29:07 +0400 |
| parents | 65a7bb156fb7 |
| children | 818c74b038ae |
| rev | line source |
|---|---|
| 0 | 1 package IMPL::DOM::Node; |
| 2 use strict; | |
| 3 use warnings; | |
| 4 | |
| 11 | 5 use base qw(IMPL::Object); |
| 0 | 6 |
| 4 | 7 use IMPL::Object::List; |
| 0 | 8 use IMPL::Class::Property; |
| 9 use IMPL::Class::Property::Direct; | |
| 10 use Scalar::Util qw(weaken); | |
| 11 | |
| 1 | 12 use IMPL::Exception; |
| 13 | |
| 0 | 14 BEGIN { |
| 4 | 15 public _direct property nodeName => prop_get | owner_set; |
| 16 public _direct property isComplex => { get => \&_getIsComplex } ; | |
| 17 public _direct property nodeValue => prop_all; | |
| 18 public _direct property childNodes => { get => \&_getChildNodes }; | |
| 19 public _direct property parentNode => prop_get ; | |
| 6 | 20 private _direct property _propertyMap => prop_get ; |
| 0 | 21 } |
| 22 | |
| 23 sub CTOR { | |
| 11 | 24 my ($this,%args) = @_; |
| 0 | 25 |
| 11 | 26 $this->nodeName($args{nodeName}) or die new IMPL::InvalidArgumentException("A name is required"); |
| 0 | 27 } |
| 28 | |
| 29 sub insertNode { | |
| 30 my ($this,$node,$pos) = @_; | |
| 4 | 31 |
| 32 die new IMPL::InvalidOperationException("You can't insert the node to itselft") if $this == $node; | |
| 33 | |
| 34 $node->{$parentNode}->removeNode($node) if ($node->{$parentNode}); | |
| 35 | |
| 36 $this->childNodes->InsertAt($pos,$node); | |
| 37 | |
| 38 $node->_setParent( $this ); | |
| 39 | |
| 40 return $node; | |
| 41 } | |
| 42 | |
| 14 | 43 sub appendNode { |
|
16
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
44 my ($this,$node) = @_; |
| 14 | 45 |
| 46 die new IMPL::InvalidOperationException("You can't insert the node to itselft") if $this == $node; | |
| 47 | |
| 48 $node->{$parentNode}->removeNode($node) if ($node->{$parentNode}); | |
| 49 | |
| 50 $this->childNodes->Append($node); | |
| 51 | |
| 52 $node->_setParent( $this ); | |
| 53 | |
| 54 return $node; | |
| 55 } | |
| 56 | |
|
16
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
57 sub appendRange { |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
58 my ($this,@range) = @_; |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
59 |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
60 die new IMPL::InvalidOperationException("You can't insert the node to itselft") if grep $_ == $this, @range; |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
61 |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
62 foreach my $node (@range) { |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
63 $node->{$parentNode}->removeNode($node) if ($node->{$parentNode}); |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
64 $node->_setParent( $this ); |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
65 } |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
66 |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
67 $this->childNodes->Append(@range); |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
68 |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
69 return $this; |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
70 } |
|
75d55f4ee263
Окончательная концепция описания схем и построения DOM документов
Sergey
parents:
14
diff
changeset
|
71 |
| 4 | 72 sub _getChildNodes { |
| 73 my ($this) = @_; | |
| 74 | |
| 75 $this->{$childNodes} = new IMPL::Object::List() unless $this->{$childNodes}; | |
| 76 $this->{$childNodes}; | |
| 0 | 77 } |
| 78 | |
| 79 sub removeNode { | |
| 80 my ($this,$node) = @_; | |
| 4 | 81 |
| 82 if ($this == $node->{$parentNode}) { | |
| 83 $this->childNodes->RemoveItem($node); | |
| 84 $node->{$parentNode} = undef; | |
| 85 return $this; | |
| 86 } else { | |
| 87 die new IMPL::InvalidOperationException("The specified node isn't belong to this node"); | |
| 88 } | |
| 0 | 89 } |
| 90 | |
| 7 | 91 sub replaceNodeAt { |
| 92 my ($this,$index,$node) = @_; | |
| 93 | |
| 94 my $nodeOld = $this->childNodes->[$index]; | |
| 95 | |
| 96 die new IMPL::InvalidOperationException("You can't insert the node to itselft") if $this == $node; | |
| 97 | |
| 98 # unlink node from previous parent | |
| 99 $node->{$parentNode}->removeNode($node) if ($node->{$parentNode}); | |
| 100 | |
| 101 # replace (or set) old node | |
| 102 $this->childNodes->[$index] = $node; | |
| 103 | |
| 104 # save new parent | |
| 105 $node->_setParent( $this ); | |
| 106 | |
| 107 # unlink old node if we have one | |
| 108 $nodeOld->{$parentNode} = undef if $nodeOld; | |
| 109 | |
| 110 # return old node | |
| 111 return $nodeOld; | |
| 112 } | |
| 113 | |
| 0 | 114 sub removeAt { |
| 115 my ($this,$pos) = @_; | |
| 4 | 116 |
| 117 if ( my $node = $this->childNodes->RemoveAt($pos) ) { | |
| 118 $node->{$parentNode} = undef; | |
| 119 return $node; | |
| 120 } else { | |
| 121 return undef; | |
| 122 } | |
| 0 | 123 } |
| 124 | |
| 125 sub selectNodes { | |
| 14 | 126 my ($this,$query) = @_; |
| 127 my @result; | |
| 4 | 128 |
| 14 | 129 if (ref $query eq 'CODE') { |
| 130 @result = grep &$query($_), @{$this->childNodes}; | |
| 131 } else { | |
| 132 @result = grep $_->nodeName eq $query, @{$this->childNodes}; | |
| 133 } | |
| 4 | 134 |
| 135 return wantarray ? @result : \@result; | |
| 0 | 136 } |
| 137 | |
| 7 | 138 sub firstChild { |
| 139 @_ >=2 ? $_[0]->replaceNodeAt(0,$_[1]) : $_[0]->childNodes->[0]; | |
| 140 } | |
| 141 | |
| 4 | 142 sub _getIsComplex { |
| 143 $_[0]->childNodes->Count ? 1 : 0; | |
| 144 } | |
| 145 | |
| 146 sub _setParent { | |
| 11 | 147 my ($this,$node) = @_; |
| 4 | 148 |
| 11 | 149 $this->{$parentNode} = $node; |
| 14 | 150 # prevent from creating cyclicreferences |
| 4 | 151 weaken($this->{$parentNode}); |
| 0 | 152 } |
| 153 | |
| 154 sub text { | |
| 155 my ($this) = @_; | |
| 4 | 156 |
| 157 join '', $this->nodeValue, map $_->nodeValue, @{$this->childNodes}; | |
| 0 | 158 } |
| 159 | |
| 160 sub Property { | |
| 161 my $this = shift; | |
| 162 my $name = shift; | |
| 163 | |
| 164 if (@_) { | |
| 165 # set | |
| 6 | 166 return $this->{$_propertyMap}{$name} = shift; |
| 0 | 167 } else { |
| 6 | 168 return $this->{$_propertyMap}{$name}; |
| 0 | 169 } |
| 170 } | |
| 171 | |
| 172 1; |
