/[suikacvs]/messaging/manakai/lib/Message/DOM/NamedNodeMap.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/NamedNodeMap.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download)
Sat Jul 14 10:00:32 2007 UTC (17 years, 4 months ago) by wakaba
Branch: MAIN
CVS Tags: manakai-release-0-4-0, HEAD
Changes since 1.1: +6 -2 lines
Error occurred while calculating annotation data.
++ manakai/lib/Message/DOM/ChangeLog	14 Jul 2007 10:00:12 -0000
	* DOMConfiguration.pm: Support for |schema-type|
	and |http://suika.fam.cx/www/2006/dom-config/xml-id|.

	* NamedNodeMap (TIEHASH): Were missing.

2007-07-14  Wakaba  <wakaba@suika.fam.cx>

1 package Message::DOM::NamedNodeMap;
2 use strict;
3 our $VERSION=do{my @r=(q$Revision: 1.1 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
4 push our @ISA, 'Message::IF::NamedNodeMap';
5 require Message::DOM::DOMException;
6 require Tie::Array;
7
8 use overload
9 '@{}' => sub {
10 tie my @list, (ref $_[0]) . '::Array', $_[0];
11 return \@list;
12 },
13 '%{}' => sub {
14 tie my %list, ref $_[0], $_[0];
15 return \%list;
16 },
17 eq => sub {
18 return 0 unless UNIVERSAL::isa ($_[1], 'Message::DOM::NamedNodeMap');
19 return 0 if $_[1]->isa ('Message::DOM::NamedNodeMap::ArrayMap');
20 return (${$_[0]}->[0] eq ${$_[1]}->[0] and ${$_[0]}->[1] eq ${$_[1]}->[1]);
21 },
22 ne => sub {
23 return not ($_[0] eq $_[1]);
24 },
25 '==' => sub {
26 return 0 unless UNIVERSAL::isa ($_[1], 'Message::IF::NamedNodeMap');
27
28 local $Error::Depth = $Error::Depth + 1;
29 my $length1 = @{$_[0]};
30 my $length2 = @{$_[1]};
31 return 0 if $length1 != $length2;
32
33 for my $i (0..($length1 - 1)) {
34 my $node1 = $_[0]->[$i];
35 my $node2 = $_[1]->[$i];
36 return 0 if $node1 != $node2;
37 }
38 ## TODO: This ordering is only assumed in manakai...
39
40 return 1;
41 },
42 '!=' => sub {
43 return not ($_[0] == $_[1]);
44 },
45 fallback => 1;
46
47 sub ___report_error ($$) {
48 $_[1]->throw;
49 } # ___report_error
50
51 sub TIEHASH ($$) { $_[1] }
52
53 ## |NamedNodeMap| attributes
54
55 sub length ($) {
56 return scalar @{[map {$_} values %{${${$_[0]}->[0]}->{${$_[0]}->[1]}}]};
57 } # length
58
59 sub manakai_read_only ($) {
60 return ${${$_[0]}->[0]}->{manakai_read_only};
61 } # manakai_read_only
62
63 ## |NamedNodeMap| methods
64
65 sub get_named_item ($$) {
66 return ${${$_[0]}->[0]}->{${$_[0]}->[1]}->{$_[1]};
67 } # get_named_item
68 *FETCH = \&get_named_item;
69
70 sub get_named_item_ns ($$$) { }
71
72 sub item ($$) {
73 my $index = 0+$_[1];
74 my $list = ${${$_[0]}->[0]}->{${$_[0]}->[1]};
75
76 my $key = $index >= 0 ? [sort {$a cmp $b} keys %$list]->[$index] : undef;
77 if (defined $key and defined $list->{$key}) {
78 return $list->{$key};
79 } else {
80 return undef;
81 }
82 } # item
83
84 sub remove_named_item ($$) {
85 my $name = ''.$_[1];
86 my $list = ${${$_[0]}->[0]}->{${$_[0]}->[1]};
87
88 my $od = ${${$_[0]}->[0]}->{owner_document}; # might be undef, but no problem
89
90 my $key = ${$_[0]}->[1] eq 'attribute_definitions'
91 ? 'owner_element_type_definition' : 'owner_document_type_definition';
92
93 if ($$od->{strict_error_checking}) {
94 if (${${$_[0]}->[0]}->{manakai_read_only}) {
95 report Message::DOM::DOMException
96 -object => $_[0],
97 -type => 'NO_MODIFICATION_ALLOWED_ERR',
98 -subtype => 'READ_ONLY_NODE_ERR';
99 }
100 }
101
102 if (defined $list->{$name}) {
103 my $r = $list->{$name};
104 delete $$r->{$key};
105 delete $list->{$name};
106 return $r;
107 } else {
108 report Message::DOM::DOMException
109 -object => $_[0],
110 -type => 'NOT_FOUND_ERR',
111 -subtype => 'NOT_CHILD_ERR';
112 }
113 } # remove_named_item
114
115 sub remove_named_item_ns ($$) {
116 report Message::DOM::DOMException
117 -object => $_[0],
118 -type => 'NOT_FOUND_ERR',
119 -subtype => 'NOT_CHILD_ERR';
120 } # remove_named_item_ns
121
122 sub DELETE ($$) {
123 my $r;
124 try {
125 $r = $_[0]->remove_named_item ($_[1]);
126 } catch Message::DOM::DOMException with {
127 my $err = shift;
128 unless ($err->subtype eq 'NOT_CHILD_ERR') {
129 $err->throw;
130 }
131 };
132 return $r; ## TODO: This return value is ok?
133 } # DELETE
134
135 sub set_named_item ($$) {
136 my $od = ${${$_[0]}->[0]}->{owner_document};
137 if (not defined $od or
138 $od ne ($_[1]->owner_document || $_[1])) {
139 ## TODO: $od not defined case is manakai extension. Document it!
140 report Message::DOM::DOMException
141 -object => $_[0],
142 -type => 'WRONG_DOCUMENT_ERR',
143 -subtype => 'EXTERNAL_OBJECT_ERR';
144 }
145
146 my $key = ${$_[0]}->[1] eq 'attribute_definitions'
147 ? 'owner_element_type_definition' : 'owner_document_type_definition';
148
149 if ($$od->{strict_error_checking}) {
150 if ($_[1]->node_type !=
151 {
152 element_types => 81001, # ELEMENT_TYPE_DEFINITION_NODE
153 attribute_definitions => 81002, # ATTRIBUTE_DEFINITION_NODE
154 entities => 6, # ENTITY_NODE
155 notations => 12, # NOTATION_NODE
156 }->{${$_[0]}->[1]}) {
157 report Message::DOM::DOMException
158 -object => $_[0],
159 -type => 'HIERARCHY_REQUEST_ERR',
160 -subtype => 'CHILD_NODE_TYPE_ERR';
161 }
162
163 if (${${$_[0]}->[0]}->{manakai_read_only}) {
164 report Message::DOM::DOMException
165 -object => $_[0],
166 -type => 'NO_MODIFICATION_ALLOWED_ERR',
167 -subtype => 'READ_ONLY_NODE_ERR';
168 }
169
170 if (${$_[1]}->{$key} and not ${$_[1]}->{$key} eq ${$_[0]}->[0]) {
171 ## TODO: This is manakai extension. Document it!
172 report Message::DOM::DOMException
173 -object => $_[0],
174 -type => 'HIERARCHY_REQUEST_ERR',
175 -subtype => 'INUSE_DEFINITION_ERR';
176 }
177 }
178
179 my $name = $_[1]->node_name;
180 my $list = ${${$_[0]}->[0]}->{${$_[0]}->[1]};
181 if (defined $list->{$name}) {
182 my $r = $list->{$name};
183 if ($r eq $_[1]) {
184 ## NOTE: Replace by itself (implementation dependent).
185 return undef;
186 } else {
187 $list->{$name} = $_[1];
188 ${$_[1]}->{$key} = ${$_[0]}->[0];
189 Scalar::Util::weaken (${$_[1]}->{$key});
190 delete $$r->{$key};
191 return $r;
192 }
193 } else {
194 $list->{$name} = $_[1];
195 ${$_[1]}->{$key} = ${$_[0]}->[0];
196 Scalar::Util::weaken (${$_[1]}->{$key});
197 return undef;
198 }
199 } # set_named_item
200
201 sub set_named_item_ns ($$) {
202 report Message::DOM::DOMException
203 -object => $_[0],
204 -type => 'HIERARCHY_REQUEST_ERR',
205 -subtype => 'CHILD_NODE_TYPE_ERR';
206 } # set_named_item_ns
207
208 sub EXISTS ($$) {
209 return exists ${${$_[0]}->[0]}->{${$_[0]}->[1]}->{$_[1]};
210 } # EXISTS
211
212 sub FIRSTKEY ($) {
213 my $list = ${${$_[0]}->[0]}->{${$_[0]}->[1]};
214 my $a = keys %$list; # reset
215 return each %$list;
216 } # FIRSTKEY
217
218 sub NEXTKEY ($) {
219 return each %{${${$_[0]}->[0]}->{${$_[0]}->[1]}};
220 } # NEXTKEY
221
222 sub SCALAR ($) {
223 return scalar %{${${$_[0]}->[0]}->{${$_[0]}->[1]}};
224 } # SCALAR
225
226 package Message::DOM::NamedNodeMap::Array;
227 push our @ISA, 'Tie::Array';
228
229 sub DELETE ($$) {
230 my $item = $_[0]->item ($_[1]);
231 if ($item) {
232 local $Error::Depth = $Error::Depth + 1;
233 return $_[0]->remove_named_item ($item->node_name);
234 } else {
235 return undef;
236 }
237 } # DELETE
238
239 sub EXISTS ($$) {
240 return ($_[1] < $_[0]->length);
241 } # EXISTS
242
243 *FETCH = \&Message::DOM::NamedNodeMap::item;
244
245 *FETCHSIZE = \&Message::DOM::NamedNodeMap::length;
246
247 ## TODO: |STORE|
248
249 sub STORESIZE ($) {
250 local $Error::Depth = $Error::Depth + 1;
251 my $length = $_[0]->length;
252 if ($length > $_[1]) {
253 for (my $i = $length - 1; $i >= $_[1]; $i--) {
254 my $item = $_[0]->item ($i);
255 $_[0]->remove_named_item ($item->node_name);
256 }
257 }
258 } # STORESIZE
259
260 sub TIEARRAY ($$) { bless \[${$_[1]}->[0], ${$_[1]}->[1]], __PACKAGE__ }
261
262 package Message::DOM::NamedNodeMap::AttrMap;
263 push our @ISA, 'Message::DOM::NamedNodeMap';
264
265 use overload
266 eq => sub {
267 return 0 unless UNIVERSAL::isa ($_[1], 'Message::DOM::NamedNodeMap');
268 return $${$_[0]} eq $${$_[1]};
269 },
270 fallback => 1;
271
272 sub TIEHASH ($$) { $_[1] }
273
274 ## |NamedNodeMap| attributes
275
276 sub length ($) {
277 my $list = ${$${$_[0]}}->{manakai_content_attribute_list};
278 if (defined $list) {
279 return scalar @$list;
280 } else {
281 $list = ${$${$_[0]}}->{attributes};
282 my $r = 0;
283 for my $l (values %$list) {
284 $r += grep {$l->{$_}} keys %$l;
285 }
286 return $r;
287 }
288 } # length
289
290 sub manakai_read_only ($) {
291 return ${$${$_[0]}}->{manakai_read_only};
292 } # manakai_read_only
293
294 ## |NamedNodeMap| methods
295
296 sub get_named_item ($$) {
297 local $Error::Depth = $Error::Depth + 1;
298 return $${$_[0]}->get_attribute_node ($_[1]);
299 } # get_named_item
300 *FETCH = \&get_named_item;
301
302 sub get_named_item_ns ($$$) {
303 local $Error::Depth = $Error::Depth + 1;
304 return $${$_[0]}->get_attribute_node_ns ($_[1], $_[2]);
305 } # get_named_item_ns
306
307 sub item ($$) {
308 ## Update the sorted content attribute name list
309 my $list = ${$${$_[0]}}->{manakai_content_attribute_list};
310 my $attrs = ${$${$_[0]}}->{attributes};
311 unless (defined $list) {
312 $list = [];
313 for my $ns (sort {$a cmp $b} keys %{$attrs}) {
314 push @$list, map {[$ns => $_]} sort {$a cmp $b} keys %{$attrs->{$ns}};
315 }
316 ${$${$_[0]}}->{manakai_content_attribute_list} = $list;
317 }
318
319 my $index = 0+$_[1];
320 return $attrs->{$list->[$index]->[0]}->{$list->[$index]->[1]};
321 } # item
322
323 sub remove_named_item ($$) {
324 my $el = $${$_[0]};
325 local $Error::Depth = $Error::Depth + 1;
326 my $node = $el->get_attribute_node ($_[1]);
327 unless ($node) {
328 local $Error::Depth = $Error::Depth - 1;
329 report Message::DOM::DOMException
330 -object => $_[0],
331 -type => 'NOT_FOUND_ERR',
332 -subtype => 'NOT_CHILD_ERR';
333 }
334 return $el->remove_attribute_node ($node);
335 } # remove_named_item
336
337 sub remove_named_item_ns ($$) {
338 my $el = $${$_[0]};
339 local $Error::Depth = $Error::Depth + 1;
340 my $node = $el->get_attribute_node_ns ($_[1], $_[2]);
341 unless ($node) {
342 local $Error::Depth = $Error::Depth - 1;
343 report Message::DOM::DOMException
344 -object => $_[0],
345 -type => 'NOT_FOUND_ERR',
346 -subtype => 'NOT_CHILD_ERR';
347 }
348 return $el->remove_attribute_node ($node);
349 } # remove_named_item_ns
350
351 sub set_named_item ($$) {
352 if ($_[1]->node_type != 2) { # ATTRIBUTE_NODE
353 report Message::DOM::DOMException
354 -object => $_[0],
355 -type => 'HIERARCHY_REQUEST_ERR',
356 -subtype => 'CHILD_NODE_TYPE_ERR';
357 }
358
359 local $Error::Depth = $Error::Depth + 1;
360 return $${$_[0]}->set_attribute_node ($_[1]);
361 } # set_named_item
362
363 sub set_named_item_ns ($$) {
364 if ($_[1]->node_type != 2) { # ATTRIBUTE_NODE
365 report Message::DOM::DOMException
366 -object => $_[0],
367 -type => 'HIERARCHY_REQUEST_ERR',
368 -subtype => 'CHILD_NODE_TYPE_ERR';
369 }
370
371 local $Error::Depth = $Error::Depth + 1;
372 return $${$_[0]}->set_attribute_node_ns ($_[1]);
373 } # set_named_item_ns
374
375 sub EXISTS ($$) {
376 local $Error::Depth = $Error::Depth + 1;
377 return defined ($_[0]->get_named_item ($_[1]));
378 } # EXISTS
379
380 sub FIRSTKEY ($) {
381 local $Error::Depth = $Error::Depth + 1;
382 my $node = $_[0]->item (0);
383 ${$${$_[0]}}->{manakai_hash_position} = 1;
384 return $node ? $node->node_name : undef;
385 } # FIRSTKEY
386
387 sub NEXTKEY ($) {
388 my $i = ${$${$_[0]}}->{manakai_hash_position}++;
389 my $node = $_[0]->item ($i);
390 return $node ? $node->node_name : undef;
391 } # NEXTKEY
392
393 sub SCALAR ($) {
394 local $Error::Depth = $Error::Depth + 1;
395 return $${$_[0]}->has_attributes;
396 } # SCALAR
397
398 package Message::DOM::NamedNodeMap::AttrMap::Array;
399 push our @ISA, 'Tie::Array';
400
401 sub DELETE ($$) {
402 my $item = $_[0]->item ($_[1]);
403 if ($item) {
404 local $Error::Depth = $Error::Depth + 1;
405 return $_[0]->remove_named_item_ns
406 ($item->namespace_uri, $item->manakai_local_name);
407 } else {
408 return undef;
409 }
410 } # DELETE
411
412 sub EXISTS ($$) {
413 return ($_[1] < $_[0]->length);
414 } # EXISTS
415
416 *FETCH = \&Message::DOM::NamedNodeMap::AttrMap::item;
417
418 *FETCHSIZE = \&Message::DOM::NamedNodeMap::AttrMap::length;
419
420 sub STORESIZE ($) {
421 local $Error::Depth = $Error::Depth + 1;
422 my $length = $_[0]->length;
423 if ($length > $_[1]) {
424 for (my $i = $length - 1; $i >= $_[1]; $i--) {
425 my $item = $_[0]->item ($i);
426 $_[0]->remove_named_item_ns
427 ($item->namespace_uri, $item->manakai_local_name);
428 }
429 }
430 } # STORESIZE
431
432 sub TIEARRAY ($$) { bless \\$${$_[1]}, __PACKAGE__ }
433
434 package Message::IF::NamedNodeMap;
435
436 =head1 LICENSE
437
438 Copyright 2007 Wakaba <w@suika.fam.cx>
439
440 This program is free software; you can redistribute it and/or
441 modify it under the same terms as Perl itself.
442
443 =cut
444
445 1;
446 ## $Date: 2007/07/08 07:59:02 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24