File Coverage

blib/lib/XML/Validator/Schema/SimpleTypeNode.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 32 0.0
condition 0 14 0.0
subroutine 5 11 45.4
pod 0 6 0.0
total 20 131 15.2


line stmt bran cond sub pod time code
1             package XML::Validator::Schema::SimpleTypeNode;
2 5     5   23 use base 'XML::Validator::Schema::Node';
  5         10  
  5         421  
3 5     5   25 use strict;
  5         8  
  5         134  
4 5     5   30 use warnings;
  5         10  
  5         160  
5              
6 5     5   26 use XML::Validator::Schema::Util qw(_attr _err);
  5         7  
  5         378  
7 5     5   39 use Carp qw(confess);
  5         9  
  5         4841  
8              
9             =head1 NAME
10              
11             XML::Validator::Schema::SimpleTypeNode
12              
13             =head1 DESCRIPTION
14              
15             Temporary node in the schema parse tree to represent a simpleType.
16              
17             =cut
18              
19             # Hash mapping facet names to allowable values
20             our %FACET_VALUE = (length => "nonNegativeInteger",
21             minLength => "nonNegativeInteger",
22             maxLength => "nonNegativeInteger",
23             totalDigits => "positiveInteger",
24             fractionDigits => "nonNegativeInteger");
25              
26             sub parse {
27 0     0 0   my ($pkg, $data) = @_;
28 0           my $self = $pkg->new();
29              
30 0           my $name = _attr($data, 'name');
31 0 0         $self->name($name) if $name;
32              
33 0           $self->{restrictions} = {};
34              
35 0           return $self;
36             }
37              
38             sub parse_restriction {
39 0     0 0   my ($self, $data) = @_;
40              
41 0           my $base = _attr($data, 'base');
42 0 0         _err("Found restriction without required 'base' attribute.")
43             unless $base;
44 0           $self->{base} = $base;
45             }
46              
47             sub parse_facet {
48 0     0 0   my ($self, $data) = @_;
49 0           my $facet = $data->{LocalName};
50              
51 0           my $value = _attr($data, 'value');
52 0 0         _err("Found facet <$facet> without required 'value' attribute.")
53             unless defined $value;
54 0 0         $self->check_facet_value($facet, $value, $FACET_VALUE{$facet}) if defined $FACET_VALUE{$facet};
55              
56 0   0       push @{$self->{restrictions}{$facet} ||= []}, $value;
  0            
57             }
58              
59             sub compile {
60 0     0 0   my ($self) = shift;
61              
62 0 0         if ( $self->{mother}->{is_union} ) {
63 0           my $mum=$self->{mother};
64 0           $self->{name} = $mum->{name} .
65             $mum->{next_instance};
66 0           $self->{mother}->{next_instance} ++;
67             }
68              
69             # If my only child is a union, everything is already compiled
70              
71 0 0         if ( $self->{got_union} ) {
72             # all compilation done at lower level
73             # it looks sort of inappropriate to return a string when
74             # everything is expecting a SimpleType in here. But my view is that
75             # a union isn't really a simpletype and it isn't appropriate to
76             # handle a union directly in SimpleType. This alerts ElementNode
77             # to the fact that it has to do a little extra work.
78 0           return 'union';
79             }
80             # compile a new type
81 0           my $base = $self->root->{type_library}->find(name => $self->{base});
82 0           my $type = $base->derive();
83            
84             # smoke 'em if you got 'em
85 0 0         $type->{name} = $self->{name} if $self->{name};
86            
87             # add restrictions
88 0           foreach my $facet (keys %{$self->{restrictions}}) {
  0            
89 0           foreach my $value (@{$self->{restrictions}{$facet}}) {
  0            
90 0 0         if ($facet eq 'pattern') {
91 0           $type->restrict($facet, qr/^$value$/);
92             } else {
93 0           $type->restrict($facet, $value);
94             }
95             }
96             }
97              
98             # register in the library if this is a named type
99 0 0         $self->root->{type_library}->add(name => $self->{name},
100             obj => $type)
101             if $self->{name};
102              
103 0 0         if ( $self->{mother}->{is_union} ) {
104             # update great-gran with this simple type member
105             # However this node is a SimpleTypeNode, and to make simple
106             # re-use of 'check' possible in ElementNode, what we should
107             # be pushing is an ElementNode
108              
109 0           my $gg = $self->{mother}->{mother}->{mother};
110             # Make a new elementnode to stuff into members
111 0           my $mbr = XML::Validator::Schema::ElementNode->new();
112              
113 0           $mbr->{type} = $type;
114             # make this simpletype the daughter of the new member element:
115 0           $mbr->add_daughter($self);
116 0           push(@{$gg->{members}},$mbr);
  0            
117             }
118              
119 0           return $type;
120             }
121              
122             sub check_facet_value {
123 0     0 0   my ($self, $facet, $value, $type_name) = @_;
124 0           my ($ok, $msg) = $self->root->{type_library}->find(name => $type_name)->check($value);
125 0 0         _err("Facet <$facet> value $value is not a $type_name")
126             unless $ok;
127             }
128              
129             sub check_constraints {
130 0     0 0   my ($self) = @_;
131 0           my $r = $self->{restrictions};
132              
133             # Schema Component Constraint: fractionDigits-totalDigits
134 0 0 0       if (exists $r->{fractionDigits} && exists $r->{totalDigits}) {
135 0 0         _err("Facet value $r->{fractionDigits}[0] is greater than facet value $r->{totalDigits}[0]")
136             if ($r->{fractionDigits}[0] > $r->{totalDigits}[0]);
137             }
138              
139             # Schema Component Constraint: length-minLength-maxLength
140 0 0 0       _err("Facet is defined in addition to facets or ")
      0        
141             if (exists $r->{length} && (exists $r->{minLength} || exists $r->{maxLength}));
142              
143             # Schema Component Constraint: minLength-less-than-equal-to-maxLength
144 0 0 0       if (exists $r->{minLength} && exists $r->{maxLength}) {
145 0 0         _err("Facet value $r->{minLength}[0] is greater than than facet value $r->{maxLength}[0]")
146             if ($r->{minLength}[0] > $r->{maxLength}[0]);
147             }
148             }
149              
150             1;