| 49 | 1 package IMPL::DOM::Schema::NodeList; | 
|  | 2 use strict; | 
|  | 3 use warnings; | 
| 165 | 4 use parent qw(IMPL::DOM::Node); | 
| 49 | 5 | 
|  | 6 use IMPL::Class::Property; | 
| 152 | 7 use IMPL::DOM::Property qw(_dom); | 
| 49 | 8 require IMPL::DOM::Schema::ValidationError; | 
|  | 9 | 
|  | 10 our %CTOR = ( | 
|  | 11     'IMPL::DOM::Node' => sub { nodeName => 'NodeList' } | 
|  | 12 ); | 
|  | 13 | 
|  | 14 BEGIN { | 
| 152 | 15     public _dom property messageUnexpected => prop_all; | 
|  | 16     public _dom property messageNodesRequired => prop_all; | 
| 49 | 17 } | 
|  | 18 | 
|  | 19 sub CTOR { | 
|  | 20     my ($this,%args) = @_; | 
|  | 21 | 
| 238 | 22     $this->messageUnexpected($args{messageUnexpected} || 'A %node.nodeName% isn\'t allowed in %node.parentNode.path%'); | 
|  | 23     $this->messageNodesRequired($args{messageNodesRequired} || 'A %schema.name% is required in the node %parent.path%'); | 
| 49 | 24 } | 
|  | 25 | 
|  | 26 sub Validate { | 
| 125 | 27     my ($this,$node,$ctx) = @_; | 
| 49 | 28 | 
|  | 29     my @nodes = map { | 
|  | 30         {nodeName => $_->name, anyNode => $_->isa('IMPL::DOM::Schema::AnyNode') , Schema => $_, Max => $_->maxOccur eq 'unbounded' ? undef : $_->maxOccur, Min => $_->minOccur, Seen => 0 } | 
|  | 31     } @{$this->childNodes}; | 
|  | 32 | 
|  | 33     my $info = shift @nodes; | 
| 125 | 34     my $sourceSchema = $ctx->{Source} || $this->parentNode; | 
| 49 | 35 | 
|  | 36     foreach my $child ( @{$node->childNodes} ) { | 
|  | 37         #skip schema elements | 
|  | 38         while ($info and not $info->{anyNode} and $info->{nodeName} ne $child->nodeName) { | 
|  | 39             # if possible of course :) | 
|  | 40             return new IMPL::DOM::Schema::ValidationError ( | 
| 236 | 41                 message => $this->messageUnexpected, | 
|  | 42                 node => $child, | 
|  | 43                 parent => $node, | 
|  | 44                 schema => $info->{Schema}, | 
|  | 45                 source => $sourceSchema | 
| 49 | 46             ) if $info->{Min} > $info->{Seen}; | 
|  | 47 | 
|  | 48             $info = shift @nodes; | 
|  | 49         } | 
|  | 50 | 
|  | 51         # return error if no more children allowed | 
|  | 52         return new IMPL::DOM::Schema::ValidationError ( | 
| 236 | 53             message => $this->messageUnexpected, | 
|  | 54             node => $child, | 
|  | 55             parent => $node, | 
|  | 56             source => $sourceSchema | 
| 49 | 57         ) unless $info; | 
|  | 58 | 
|  | 59         # it's ok, we found schema element for child | 
|  | 60         # but it may be any node or switching node wich would not satisfy current child | 
|  | 61 | 
|  | 62         # validate | 
|  | 63         while (my @errors = $info->{Schema}->Validate($child)) { | 
|  | 64             if( $info->{anyNode} and $info->{Seen} >= $info->{Min} ) { | 
|  | 65                 # in case of any or switch node, skip it if possible | 
|  | 66                 next if $info = shift @nodes; | 
|  | 67             } | 
|  | 68             return @errors; | 
|  | 69         } | 
|  | 70 | 
|  | 71         $info->{Seen}++; | 
|  | 72 | 
|  | 73         # check count limits | 
|  | 74         return new IMPL::DOM::Schema::ValidationError ( | 
| 236 | 75             message => $this->messageUnexpected, | 
|  | 76             node => $child, | 
|  | 77             parent => $node, | 
|  | 78             source => $sourceSchema, | 
| 49 | 79         ) if $info->{Max} and $info->{Seen} > $info->{Max}; | 
|  | 80     } | 
|  | 81 | 
|  | 82     # no more children left (but may be should :) | 
|  | 83     while ($info) { | 
|  | 84         return new IMPL::DOM::Schema::ValidationError ( | 
| 236 | 85             error => 1, | 
|  | 86             message => $this->messageNodesRequired, | 
|  | 87             source => $sourceSchema, | 
|  | 88             parent => $node, | 
|  | 89             schema => $info->{Schema} | 
| 49 | 90         ) if $info->{Seen} < $info->{Min}; | 
|  | 91 | 
|  | 92         $info = shift @nodes; | 
|  | 93     } | 
|  | 94     return; | 
|  | 95 } | 
|  | 96 | 
|  | 97 1; | 
|  | 98 | 
|  | 99 __END__ | 
|  | 100 | 
|  | 101 =pod | 
|  | 102 | 
|  | 103 =head1 DESCRIPTION | 
|  | 104 | 
| 180 | 105 Содержимое для сложного узла. Порядок важен. Дочерними элементами могут быть | 
|  | 106 только C<IMPL::DOM::Schema::ComplexNode> и C<IMPL::DOM::Schema::SimpleNode>. | 
| 49 | 107 | 
|  | 108 =cut |