File Coverage

lib/XML/Schema/Particle.pm
Criterion Covered Total %
statement 59 73 80.8
branch 24 42 57.1
condition 3 6 50.0
subroutine 15 16 93.7
pod 1 11 9.0
total 102 148 68.9


line stmt bran cond sub pod time code
1             #============================================================= -*-perl-*-
2             #
3             # XML::Schema::Particle.pm
4             #
5             # DESCRIPTION
6             # A particle is an element within a content model optionally
7             # specified with minOccurs and maxOccurs constraints.
8             #
9             # AUTHOR
10             # Andy Wardley
11             #
12             # COPYRIGHT
13             # Copyright (C) 2001 Canon Research Centre Europe Ltd.
14             # All Rights Reserved.
15             #
16             # This module is free software; you can redistribute it and/or
17             # modify it under the same terms as Perl itself.
18             #
19             # REVISION
20             # $Id: Particle.pm,v 1.1.1.1 2001/08/29 14:30:17 abw Exp $
21             #
22             #========================================================================
23              
24             package XML::Schema::Particle;
25              
26 10     10   614 use strict;
  10         20  
  10         378  
27 10     10   61 use XML::Schema;
  10         23  
  10         231  
28 10     10   54 use base qw( XML::Schema::Base );
  10         22  
  10         891  
29 10     10   54 use vars qw( $VERSION $DEBUG $ERROR $ETYPE @MODELS );
  10         17  
  10         1747  
30              
31             $VERSION = sprintf("%d.%02d", q$Revision: 1.1.1.1 $ =~ /(\d+)\.(\d+)/);
32             $DEBUG = 0 unless defined $DEBUG;
33             $ERROR = '';
34             $ETYPE = 'particle';
35             @MODELS = qw( element sequence choice model );
36              
37              
38 10     10   74 use constant DECLINED => 0;
  10         19  
  10         10722  
39              
40             # alias min() to minOccurs() and max() to maxOccurs()
41             *minOccurs = \&min;
42             *maxOccurs = \&max;
43              
44              
45             #------------------------------------------------------------------------
46             # init()
47             #
48             # Called automatically by base class new() method.
49             #------------------------------------------------------------------------
50              
51             sub init {
52 28     28 1 56 my ($self, $config) = @_;
53 28   33     155 my $factory = $self->{ FACTORY } = $config->{ FACTORY } || $XML::Schema::FACTORY;
54 28         43 my ($content, $model, $modtype);
55 28         40 my $name = shift;
56              
57             # allow an element, sequence, choice or model object to be defined
58             # as the 'content' item, copied to the appropriate entry in the
59             # $config hash
60 28 50       88 if ($content = $config->{ content }) {
61 0         0 my $found = 0;
62 0         0 foreach $modtype (@MODELS) {
63 0 0       0 if ($factory->isa( $modtype => $content )) {
64 0         0 $config->{ $modtype } = $content;
65 0         0 $found++;
66 0         0 last;
67             }
68             }
69 0 0       0 return $self->error("cannot determine content type for [$content]")
70             unless $found;
71             }
72              
73             # now look for an element, sequence, choice or model either
74             # provided directly or copied from the 'content' item above
75 28         55 foreach $modtype (@MODELS) {
76 55 100       146 if ($model = $config->{ $modtype }) {
77 22   66     132 return $factory->adopt( "${modtype}_particle" => $self, $config )
78             || $self->error($factory->error());
79             }
80             }
81 6         36 return $self->error("particle expects one of: ", join(', ', @MODELS));
82             }
83              
84              
85             sub constrain {
86 24     24 0 45 my ($self, $config) = @_;
87 24         59 my ($min, $max) = @$config{ qw( minOccurs maxOccurs ) };
88 24 100       70 $min = $config->{ min } unless defined $min;
89 24 100       62 $max = $config->{ max } unless defined $max;
90 24 100       52 $min = 1 unless defined $min;
91 24 100       55 $max = 1 unless defined $max;
92              
93 24 100       61 return $self->error("maxOccurs ($max) is less than minOccurs ($min)")
94             if $max < $min;
95              
96 23         104 @$self{ qw( min max occurs ) } = ($min, $max, 0);
97 23 50       58 $self->TRACE("min => $min, max => $max") if $DEBUG;
98              
99 23         82 return $self;
100             }
101              
102              
103             sub type {
104 2     2 0 20 return $_[0]->{ type };
105             }
106              
107              
108             sub models {
109 27     27 0 157 return @MODELS;
110             }
111              
112              
113             sub min {
114 12     12 0 20 my $self = shift;
115 12 100       36 if (@_) {
116 1         2 my $newmin = shift;
117             return $self->error("maxOccurs ($self->{ max }) is less than minOccurs ($newmin)")
118 1 50       4 if $self->{ max } < $newmin;
119 1         13 return ($self->{ min } = $newmin);
120             }
121 11         54 return $self->{ min };
122             }
123              
124              
125             sub max {
126 13     13 0 24 my $self = shift;
127 13 50       30 if (@_) {
128 0         0 my $newmax = shift;
129             return $self->error("maxOccurs ($newmax) is less than minOccurs ($self->{ min })")
130 0 0       0 if $newmax < $self->{ min };
131 0         0 return ($self->{ max } = $newmax);
132             }
133 13         63 return $self->{ max };
134             }
135              
136              
137             sub occurs {
138 2     2 0 16 return $_[0]->{ occurs };
139             }
140              
141              
142             sub start {
143 7     7 0 10 my $self = shift;
144 7 50       17 $self->TRACE() if $DEBUG;
145 7         12 $self->{ occurs } = 0;
146 7         40 return 1;
147             }
148              
149              
150             sub element {
151 0     0 0 0 my ($self, $name) = @_;
152 0         0 return $self->error("element <$name> called in base class");
153             }
154              
155              
156             sub decline {
157 3     3 0 5 my $self = shift;
158 3         10 $self->error(@_);
159 3 50       9 $self->TRACE() if $DEBUG;
160 3         9 return DECLINED;
161             }
162              
163             sub end {
164 3     3 0 6 my $self = shift;
165 3         11 my ($min, $max, $occurs, $name )
166             = @$self{ qw( min max occurs name ) };
167              
168 3 50       10 $self->TRACE() if $DEBUG;
169              
170 3         6 $self->{ _ERROR } = '';
171              
172 3 100       27 return $self->error("minimum of $min <$name> element",
    50          
173             $min > 1 ? 's' : '', " expected")
174             if $occurs < $min;
175              
176 0 0         return $self->error("maximum of $max <$name> element",
    0          
177             $max > 1 ? 's' : '', " exceeded")
178             if $occurs > $max;
179              
180 0           return 1;
181             }
182              
183              
184             1;
185              
186             __END__