File Coverage

lib/XML/Schema/Facet/Builtin.pm
Criterion Covered Total %
statement 183 183 100.0
branch 25 30 83.3
condition 35 52 67.3
subroutine 53 53 100.0
pod n/a
total 296 318 93.0


line stmt bran cond sub pod time code
1             #============================================================= -*-perl-*-
2             #
3             # XML::Schema::Facet::Builtin
4             #
5             # DESCRIPTION
6             # Definitions of the various facets that are built in to XML Schema.
7             #
8             # AUTHOR
9             # Andy Wardley
10             #
11             # COPYRIGHT
12             # Copyright (C) 2001 Canon Research Centre Europe Ltd.
13             # All Rights Reserved.
14             #
15             # This module is free software; you can redistribute it and/or
16             # modify it under the same terms as Perl itself.
17             #
18             # REVISION
19             # $Id: Builtin.pm,v 1.1.1.1 2001/08/29 14:30:17 abw Exp $
20             #
21             #========================================================================
22              
23             package XML::Schema::Facet::Builtin;
24              
25 28     28   154 use strict;
  28         48  
  28         1182  
26 28     28   135 use base qw( XML::Schema::Facet );
  28         52  
  28         13044  
27 28     28   1662 use vars qw( $VERSION $DEBUG );
  28         57  
  28         2660  
28              
29             $VERSION = sprintf("%d.%02d", q$Revision: 1.1.1.1 $ =~ /(\d+)\.(\d+)/);
30             $DEBUG = 0 unless defined $DEBUG;
31              
32              
33             #========================================================================
34             # Fixable
35             # Base class which adds the optional 'fixed' attribute.
36             #========================================================================
37              
38             package XML::Schema::Facet::Fixable;
39 28     28   140 use base qw( XML::Schema::Facet );
  28         41  
  28         2020  
40 28     28   138 use vars qw( @OPTIONAL );
  28         56  
  28         2666  
41              
42             @OPTIONAL = qw( fixed );
43              
44             sub fixed {
45 2     2   5 my $self = shift;
46 2 100       10 return $self->{ fixed } ? 1 : 0;
47             }
48              
49              
50             #========================================================================
51             # length
52             # The length of a string in characters, the length of binary data in
53             # octets, or the length of a list in items.
54             #========================================================================
55              
56             package XML::Schema::Facet::length;
57 28     28   389 use base qw( XML::Schema::Facet::Fixable );
  28         58  
  28         21200  
58 28     28   230 use vars qw( $ERROR );
  28         59  
  28         5167  
59              
60             sub valid {
61 6     6   27 my ($self, $instance, $type) = @_;
62 6         26 my $value = $instance->{ value };
63 6         6 my $length;
64              
65 6 100       17 if (ref $value eq 'ARRAY') {
66 2         3 $length = scalar @$value;
67             return $length == $self->{ value }
68 2   66     30 || $self->invalid("list has $length elements");
69             }
70             else {
71 4         5 $length = length $value;
72             return $length == $self->{ value }
73 4   66     41 || $self->invalid("string has $length characters");
74             }
75             }
76              
77              
78             #========================================================================
79             # minLength
80             # The minimum length of a string in characters, binary data in
81             # octets, or a list in items.
82             #========================================================================
83              
84             package XML::Schema::Facet::minLength;
85 28     28   162 use base qw( XML::Schema::Facet::Fixable );
  28         59  
  28         12413  
86 28     28   163 use vars qw( $ERROR );
  28         60  
  28         4869  
87              
88             sub valid {
89 13     13   39 my ($self, $instance, $type) = @_;
90 13         23 my $value = $instance->{ value };
91 13         15 my $length;
92              
93 13 100       32 if (ref $value eq 'ARRAY') {
94 6         10 $length = scalar @$value;
95             return $length >= $self->{ value }
96 6   66     47 || $self->invalid("list has $length elements");
97             }
98             else {
99 7         6 $length = length $value;
100             return $length >= $self->{ value }
101 7   66     60 || $self->invalid("string has $length characters");
102             }
103             }
104              
105              
106             #========================================================================
107             # maxLength
108             # The maximum length of a string in characters, binary data in
109             # octets, or a list in items.
110             #========================================================================
111              
112             package XML::Schema::Facet::maxLength;
113 28     28   164 use base qw( XML::Schema::Facet::Fixable );
  28         50  
  28         13046  
114 28     28   172 use vars qw( $ERROR );
  28         58  
  28         4586  
115              
116             sub valid {
117 33     33   87 my ($self, $instance, $type) = @_;
118 33         48 my $value = $instance->{ value };
119 33         33 my $length;
120              
121 33 100       74 if (ref $value eq 'ARRAY') {
122 12         15 $length = scalar @$value;
123             return $length <= $self->{ value }
124 12   66     90 || $self->invalid("list has $length elements");
125             }
126             else {
127 21         26 $length = length $value;
128             return $length <= $self->{ value }
129 21   66     146 || $self->invalid("string has $length characters");
130             }
131             }
132              
133              
134             #========================================================================
135             # pattern
136             # Regular expression pattern.
137             #========================================================================
138              
139             package XML::Schema::Facet::pattern;
140 28     28   163 use base qw( XML::Schema::Facet );
  28         48  
  28         3828  
141              
142             sub valid {
143 28     28   55 my ($self, $instance, $type) = @_;
144              
145 28   66     1574 return ($instance->{ value } =~ /$self->{ value }/)
146             || $self->invalid("string mismatch");
147             }
148              
149              
150             #========================================================================
151             # enumeration
152             # Note: need to do numerical/string equality match based on underlying
153             # type.
154             #========================================================================
155              
156             package XML::Schema::Facet::enumeration;
157 28     28   153 use base qw( XML::Schema::Facet );
  28         65  
  28         7676  
158              
159             sub init {
160 5     5   12 my ($self, $config) = @_;
161            
162 5 50       40 $self->SUPER::init($config)
163             || return;
164              
165             # ensure value is folded to a list reference
166 5         14 my $value = $self->{ value };
167 5 100       22 $self->{ value } = [ $value ]
168             unless ref $value eq 'ARRAY';
169              
170 5         49 return $self
171             }
172              
173             sub valid {
174 12     12   55 my ($self, $instance, $type) = @_;
175 12         23 my $value = $instance->{ value };
176 12         204 my $allow = $self->{ value };
177              
178 12         22 foreach my $v (@$allow) {
179 17 100       82 return 1 if $value eq $v;
180             }
181 3         7 local $" = "', '";
182             return $self->error(
183 3   66     44 $self->{ errmsg } || "string mismatch ('$value' not in: '@$allow')"
184             );
185             }
186              
187              
188             #========================================================================
189             # whiteSpace
190             # Rule for whitespace normalisation. Value should be one of:
191             # preserve: leave intact
192             # replace: replace newlines, carriage returns and tabs with spaces
193             # collapse: as per replace, collapsing multiple whitespace into a
194             # single and stripping leading/trailing whitespaces
195             #========================================================================
196              
197             package XML::Schema::Facet::whiteSpace;
198 28     28   334 use base qw( XML::Schema::Facet::Fixable );
  28         49  
  28         12290  
199 28     28   163 use vars qw( $ERROR );
  28         53  
  28         8801  
200              
201             sub init {
202 125     125   198 my ($self, $config) = @_;
203              
204 125 50       428 $self->SUPER::init($config)
205             || return;
206              
207 125 100       1142 return $self->{ value } =~ /^preserve|replace|collapse$/
208             ? $self
209             : $self->error('value must be one of: preserve, replace, collapse')
210             }
211              
212             sub valid {
213 354     354   540 my ($self, $instance, $type) = @_;
214 354         553 my $action = $self->{ value };
215 354 100       704 return 1 if $action eq 'preserve';
216              
217 353         661 for ($instance->{ value }) {
218 353         734 s/[\r\n\t]/ /g;
219 353 100       931 if ($action eq 'collapse') {
220 351         586 s/ +/ /g;
221 351         531 s/^ +//;
222 351         958 s/ +$//;
223             }
224             }
225 353         1407 return 1;
226             }
227              
228              
229             #========================================================================
230             # maxInclusive
231             # Constrain a value to be within an inclusive upper bound.
232             #========================================================================
233              
234             package XML::Schema::Facet::maxInclusive;
235 28     28   166 use base qw( XML::Schema::Facet::Fixable );
  28         54  
  28         11537  
236 28     28   152 use vars qw( $ERROR );
  28         47  
  28         3270  
237              
238             sub valid {
239 66     66   103 my ($self, $instance, $type) = @_;
240             return $instance->{ value } <= $self->{ value }
241 66   66     390 || $self->invalid("value is $instance->{ value }");
242             }
243              
244              
245             #========================================================================
246             # maxExclusive
247             # Constrain a value to be within an exclusive upper bound.
248             #========================================================================
249              
250             package XML::Schema::Facet::maxExclusive;
251 28     28   164 use base qw( XML::Schema::Facet::Fixable );
  28         66  
  28         11576  
252 28     28   162 use vars qw( $ERROR );
  28         78  
  28         3291  
253              
254             sub valid {
255 10     10   35 my ($self, $instance, $type) = @_;
256             return $instance->{ value } < $self->{ value }
257 10   66     78 || $self->invalid("value is $instance->{ value }");
258             }
259              
260              
261             #========================================================================
262             # minInclusive
263             # Constrain a value to be within an inclusive upper bound.
264             #========================================================================
265              
266             package XML::Schema::Facet::minInclusive;
267 28     28   177 use base qw( XML::Schema::Facet::Fixable );
  28         72  
  28         11551  
268 28     28   151 use vars qw( $ERROR );
  28         53  
  28         3212  
269              
270             sub valid {
271 74     74   131 my ($self, $instance, $type) = @_;
272             return $instance->{ value } >= $self->{ value }
273 74   66     420 || $self->invalid("value is $instance->{ value }");
274             }
275              
276              
277             #========================================================================
278             # minExclusive
279             # Constrain a value to be within an exclusive upper bound.
280             #========================================================================
281              
282             package XML::Schema::Facet::minExclusive;
283 28     28   143 use base qw( XML::Schema::Facet::Fixable );
  28         46  
  28         13855  
284 28     28   160 use vars qw( $ERROR );
  28         55  
  28         3412  
285              
286             sub valid {
287 2     2   25 my ($self, $instance, $type) = @_;
288             return $instance->{ value } > $self->{ value }
289 2   66     21 || $self->invalid("value is $instance->{ value }");
290             }
291              
292              
293             #========================================================================
294             # precision
295             #========================================================================
296              
297             package XML::Schema::Facet::precision;
298 28     28   155 use base qw( XML::Schema::Facet::Fixable );
  28         54  
  28         12103  
299 28     28   159 use vars qw( $ERROR );
  28         52  
  28         2940  
300              
301             sub valid {
302 4     4   41 my ($self, $instance, $type) = @_;
303             return $instance->{ precision } <= $self->{ value }
304 4   66     46 || $self->invalid("value is $instance->{ value }");
305             }
306              
307              
308             #========================================================================
309             # scale
310             #========================================================================
311              
312             package XML::Schema::Facet::scale;
313 28     28   146 use base qw( XML::Schema::Facet::Fixable );
  28         51  
  28         12116  
314 28     28   170 use vars qw( $ERROR );
  28         62  
  28         3745  
315              
316             sub valid {
317 119     119   226 my ($self, $instance, $type) = @_;
318             return $instance->{ scale } <= $self->{ value }
319 119   66     4424 || $self->invalid("value is $instance->{ value }");
320             }
321              
322              
323             #========================================================================
324             # encoding
325             #========================================================================
326              
327             package XML::Schema::Facet::encoding;
328 28     28   158 use base qw( XML::Schema::Facet::Fixable );
  28         59  
  28         11972  
329 28     28   172 use vars qw( $ERROR );
  28         55  
  28         4278  
330              
331             sub init {
332 2     2   5 my ($self, $config) = @_;
333              
334 2 50       12 $self->SUPER::init($config)
335             || return;
336              
337 2 100       17 return $self->{ value } =~ /^hex|base64$/
338             ? $self
339             : $self->error("encoding value must be 'hex' or 'base64'")
340             }
341              
342              
343             #========================================================================
344             # duration
345             #========================================================================
346              
347             package XML::Schema::Facet::duration;
348 28     28   162 use base qw( XML::Schema::Facet::Fixable );
  28         72  
  28         12541  
349 28     28   173 use vars qw( $ERROR $TYPE );
  28         74  
  28         6458  
350              
351             sub init {
352 19     19   45 my ($self, $config) = @_;
353 19 50       100 $self->SUPER::init($config)
354             || return;
355 19   66     89 $TYPE ||= XML::Schema::Type::timeDuration->new();
356             $self->{ value } = $TYPE->instance($self->{ value })
357 19   50     94 || return $self->error('duration ' . $TYPE->error());
358 19         126 return $self;
359             }
360              
361             # custom install method which installs duration in the facet hash but not
362             # the runtime list because it doesn't have validation rules.
363              
364             sub install {
365 19     19   34 my ($self, $facets, $table) = @_;
366             # $self->DEBUG("partially installing $self into type as $self->{ name }\n");
367 19         60 $table->{ $self->{ name } } = $self;
368 19         56 return 1;
369             }
370              
371              
372             #========================================================================
373             # period
374             #========================================================================
375              
376             package XML::Schema::Facet::period;
377 28     28   203 use base qw( XML::Schema::Facet::Fixable );
  28         119  
  28         13796  
378 28     28   169 use vars qw( $ERROR $TYPE );
  28         52  
  28         6771  
379              
380             sub init {
381 19     19   39 my ($self, $config) = @_;
382 19 50       98 $self->SUPER::init($config)
383             || return;
384 19   66     176 $TYPE ||= XML::Schema::Type::timeDuration->new();
385             $self->{ value } = $TYPE->instance($self->{ value })
386 19   100     113 || return $self->error('period ' . $TYPE->error());
387 18         123 return $self;
388             }
389              
390             # as per duration
391              
392             sub install {
393 18     18   41 my ($self, $facets, $table) = @_;
394             # $self->DEBUG("partially installing $self into type as $self->{ name }\n");
395 18         52 $table->{ $self->{ name } } = $self;
396 18         65 return 1;
397             }
398              
399              
400              
401             1;
402             __END__