line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
19
|
|
|
19
|
|
240
|
use 5.10.1; |
|
19
|
|
|
|
|
57
|
|
2
|
19
|
|
|
19
|
|
99
|
use strict; |
|
19
|
|
|
|
|
28
|
|
|
19
|
|
|
|
|
383
|
|
3
|
19
|
|
|
19
|
|
83
|
use warnings; |
|
19
|
|
|
|
|
33
|
|
|
19
|
|
|
|
|
613
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
package Data::Processor::Validator; |
6
|
|
|
|
|
|
|
|
7
|
19
|
|
|
19
|
|
90
|
use Carp; |
|
19
|
|
|
|
|
29
|
|
|
19
|
|
|
|
|
1104
|
|
8
|
19
|
|
|
19
|
|
105
|
use Scalar::Util qw(blessed); |
|
19
|
|
|
|
|
37
|
|
|
19
|
|
|
|
|
934
|
|
9
|
|
|
|
|
|
|
|
10
|
19
|
|
|
19
|
|
139
|
use Data::Processor::Error::Collection; |
|
19
|
|
|
|
|
29
|
|
|
19
|
|
|
|
|
785
|
|
11
|
19
|
|
|
19
|
|
6311
|
use Data::Processor::Transformer; |
|
19
|
|
|
|
|
43
|
|
|
19
|
|
|
|
|
39369
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# XXX document this with pod. (if standalone) |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Data::Processor::Validator - Validate Data Against a Schema |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub new { |
19
|
191
|
|
|
191
|
0
|
414
|
my $class = shift; |
20
|
191
|
|
|
|
|
297
|
my $schema = shift; |
21
|
191
|
|
|
|
|
603
|
my %p = @_; |
22
|
|
|
|
|
|
|
my $self = { |
23
|
|
|
|
|
|
|
schema => $schema // confess ('cannot validate without "schema"'), |
24
|
|
|
|
|
|
|
data => $p{data} // undef, |
25
|
|
|
|
|
|
|
verbose=> $p{verbose} // undef, |
26
|
|
|
|
|
|
|
errors => $p{errors} // Data::Processor::Error::Collection->new(), |
27
|
|
|
|
|
|
|
depth => $p{depth} // 0, |
28
|
|
|
|
|
|
|
indent => $p{indent} // 4, |
29
|
191
|
|
33
|
|
|
1991
|
parent_keys => $p{parent_keys} // ['root'], |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
30
|
|
|
|
|
|
|
transformer => Data::Processor::Transformer->new(), |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
}; |
33
|
191
|
|
|
|
|
387
|
bless ($self, $class); |
34
|
191
|
|
|
|
|
862
|
return $self; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# (recursively) checks data, or a section thereof, |
38
|
|
|
|
|
|
|
# by instantiating D::P::V objects and calling validate on them |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub validate { |
41
|
188
|
|
|
188
|
0
|
925
|
my $self = shift; |
42
|
188
|
|
|
|
|
362
|
$self->{data} = shift; |
43
|
188
|
100
|
|
|
|
995
|
croak ('cannot validate without "data"') unless $self->{data}; |
44
|
187
|
|
|
|
|
438
|
$self->{errors} = Data::Processor::Error::Collection->new(); |
45
|
|
|
|
|
|
|
|
46
|
187
|
|
|
|
|
487
|
$self->_add_defaults(); |
47
|
|
|
|
|
|
|
|
48
|
187
|
|
|
|
|
323
|
for my $key (keys %{$self->{data}}){ |
|
187
|
|
|
|
|
474
|
|
49
|
280
|
|
|
|
|
844
|
$self->explain (">>'$key'"); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# the shema key is ? |
52
|
|
|
|
|
|
|
# from here we know to have a "twin" key $schema_key in the schema |
53
|
280
|
100
|
|
|
|
621
|
my $schema_key = $self->_schema_twin_key($key) or next; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# transformer (transform first) |
56
|
272
|
|
|
|
|
651
|
my $e = $self->{transformer}->transform($key,$schema_key, $self); |
57
|
272
|
100
|
|
|
|
476
|
$self->error($e) if $e; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# now validate |
60
|
272
|
|
|
|
|
806
|
$self->__value_is_valid( $key ); |
61
|
272
|
|
|
|
|
737
|
$self->__validator_returns_undef($key, $schema_key); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# skip if explicitly asked for |
65
|
272
|
50
|
|
|
|
587
|
if ($self->{schema}->{$schema_key}->{no_descend_into}){ |
66
|
0
|
|
|
|
|
0
|
$self->explain ( |
67
|
|
|
|
|
|
|
">>skipping '$key' because schema explicitly says so.\n"); |
68
|
0
|
|
|
|
|
0
|
next; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
# skip data branch if schema key is empty. |
71
|
272
|
100
|
|
|
|
328
|
if (! %{$self->{schema}->{$schema_key}}){ |
|
272
|
|
|
|
|
581
|
|
72
|
7
|
|
|
|
|
25
|
$self->explain (">>skipping '$key' because schema key is empty\n'"); |
73
|
7
|
|
|
|
|
15
|
next; |
74
|
|
|
|
|
|
|
} |
75
|
265
|
100
|
|
|
|
607
|
if (! $self->{schema}->{$schema_key}->{members}){ |
76
|
168
|
|
|
|
|
450
|
$self->explain ( |
77
|
|
|
|
|
|
|
">>not descending into '$key'. No members specified\n" |
78
|
|
|
|
|
|
|
); |
79
|
168
|
|
|
|
|
324
|
next; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# recursion if we reach this point. |
83
|
97
|
|
|
|
|
339
|
$self->explain (">>descending into '$key'\n"); |
84
|
|
|
|
|
|
|
|
85
|
97
|
100
|
66
|
|
|
385
|
if (ref $self->{data}->{$key} eq ref {} ){ |
|
|
100
|
|
|
|
|
|
86
|
92
|
|
|
|
|
282
|
$self->explain |
87
|
|
|
|
|
|
|
(">>'$key' is not a leaf and we descend into it\n"); |
88
|
|
|
|
|
|
|
my $e = Data::Processor::Validator->new( |
89
|
|
|
|
|
|
|
$self->{schema}->{$schema_key}->{members}, |
90
|
92
|
|
|
|
|
345
|
parent_keys => [@{$self->{parent_keys}}, $key], |
91
|
|
|
|
|
|
|
depth => $self->{depth}+1, |
92
|
|
|
|
|
|
|
verbose => $self->{verbose}, |
93
|
|
|
|
|
|
|
|
94
|
92
|
|
|
|
|
202
|
) ->validate($self->{data}->{$key}); |
95
|
92
|
|
|
|
|
594
|
$self->{errors}->add_collection($e); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
elsif ((ref $self->{data}->{$key} eq ref []) |
99
|
|
|
|
|
|
|
&& $self->{schema}->{$schema_key}->{array}){ |
100
|
|
|
|
|
|
|
|
101
|
2
|
|
|
|
|
8
|
$self->explain( |
102
|
|
|
|
|
|
|
">>'$key' is an array reference so we check all elements\n"); |
103
|
2
|
|
|
|
|
3
|
for my $member (@{$self->{data}->{$key}}){ |
|
2
|
|
|
|
|
7
|
|
104
|
|
|
|
|
|
|
next if !defined $member |
105
|
5
|
50
|
66
|
|
|
17
|
&& $self->{schema}->{$schema_key}->{allow_empty}; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
my $e = Data::Processor::Validator->new( |
108
|
|
|
|
|
|
|
$self->{schema}->{$schema_key}->{members}, |
109
|
4
|
|
|
|
|
33
|
parent_keys => [@{$self->{parent_keys}}, $key], |
110
|
|
|
|
|
|
|
depth => $self->{depth}+1, |
111
|
|
|
|
|
|
|
verbose => $self->{verbose}, |
112
|
|
|
|
|
|
|
|
113
|
4
|
|
|
|
|
8
|
) ->validate($member); |
114
|
4
|
|
|
|
|
29
|
$self->{errors}->add_collection($e); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
# Make sure that key in data is a leaf in schema. |
118
|
|
|
|
|
|
|
# We cannot descend into a non-existing branch in data |
119
|
|
|
|
|
|
|
# but it might be required by the schema. |
120
|
|
|
|
|
|
|
else { |
121
|
3
|
|
|
|
|
12
|
$self->explain(">>checking data key '$key' which is a leaf.."); |
122
|
3
|
50
|
|
|
|
8
|
if ($self->{schema}->{$schema_key}->{members}){ |
123
|
3
|
|
|
|
|
19
|
$self->explain("but schema requires members.\n"); |
124
|
3
|
|
|
|
|
13
|
$self->error("'$key' should have members"); |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
else { |
127
|
0
|
|
|
|
|
0
|
$self->explain("schema key is also a leaf. ok.\n"); |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
# look for missing non-optional keys in schema |
132
|
|
|
|
|
|
|
# this is only done on this level. |
133
|
|
|
|
|
|
|
# Otherwise "mandatory" inherited "upwards". |
134
|
187
|
|
|
|
|
480
|
$self->_check_mandatory_keys(); |
135
|
187
|
|
|
|
|
584
|
return $self->{errors}; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
################# |
139
|
|
|
|
|
|
|
# internal methods |
140
|
|
|
|
|
|
|
################# |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# add an error |
143
|
|
|
|
|
|
|
sub error { |
144
|
39
|
|
|
39
|
0
|
62
|
my $self = shift; |
145
|
39
|
|
|
|
|
71
|
my $string = shift; |
146
|
|
|
|
|
|
|
$self->{errors}->add( |
147
|
|
|
|
|
|
|
message => $string, |
148
|
|
|
|
|
|
|
path => $self->{parent_keys}, |
149
|
39
|
|
|
|
|
138
|
); |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# explains what we are doing. |
153
|
|
|
|
|
|
|
sub explain { |
154
|
3794
|
|
|
3794
|
0
|
4356
|
my $self = shift; |
155
|
3794
|
|
|
|
|
4162
|
my $string = shift; |
156
|
3794
|
|
|
|
|
5539
|
my $indent = ' ' x ($self->{depth}*$self->{indent}); |
157
|
3794
|
|
|
|
|
6925
|
$string =~ s/>>/$indent/; |
158
|
3794
|
100
|
|
|
|
7477
|
print $string if $self->{verbose}; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# add defaults. Go over all keys *on that level* and if there is not |
163
|
|
|
|
|
|
|
# a value (or, most oftenly, a key) in data, add the key and the |
164
|
|
|
|
|
|
|
# default value. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub _add_defaults{ |
167
|
187
|
|
|
187
|
|
243
|
my $self = shift; |
168
|
|
|
|
|
|
|
|
169
|
187
|
|
|
|
|
232
|
for my $key (keys %{$self->{schema}}){ |
|
187
|
|
|
|
|
678
|
|
170
|
1244
|
100
|
|
|
|
2502
|
next unless $self->{schema}->{$key}->{default}; |
171
|
|
|
|
|
|
|
$self->{data}->{$key} = $self->{schema}->{$key}->{default} |
172
|
1
|
50
|
|
|
|
5
|
unless $self->{data}->{$key}; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# check mandatory: look for mandatory fields in all hashes 1 level |
177
|
|
|
|
|
|
|
# below current level (in schema) |
178
|
|
|
|
|
|
|
# for each check if $data has a key. |
179
|
|
|
|
|
|
|
sub _check_mandatory_keys{ |
180
|
187
|
|
|
187
|
|
289
|
my $self = shift; |
181
|
|
|
|
|
|
|
|
182
|
187
|
|
|
|
|
212
|
for my $key (keys %{$self->{schema}}){ |
|
187
|
|
|
|
|
563
|
|
183
|
1244
|
|
|
|
|
2803
|
$self->explain(">>Checking if '$key' is mandatory: "); |
184
|
1244
|
100
|
66
|
|
|
3533
|
unless ($self->{schema}->{$key}->{optional} |
185
|
|
|
|
|
|
|
and $self->{schema}->{$key}->{optional}){ |
186
|
|
|
|
|
|
|
|
187
|
81
|
|
|
|
|
182
|
$self->explain("true\n"); |
188
|
81
|
100
|
|
|
|
197
|
next if defined $self->{data}->{$key}; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# regex-keys never directly occur. |
191
|
20
|
100
|
|
|
|
53
|
if ($self->{schema}->{$key}->{regex}){ |
192
|
10
|
|
|
|
|
22
|
$self->explain(">>regex enabled key found. "); |
193
|
10
|
|
|
|
|
43
|
$self->explain("Checking data keys.. "); |
194
|
10
|
|
|
|
|
17
|
my $c = 0; |
195
|
|
|
|
|
|
|
# look which keys match the regex |
196
|
10
|
|
|
|
|
16
|
for my $c_key (keys %{$self->{data}}){ |
|
10
|
|
|
|
|
26
|
|
197
|
19
|
100
|
|
|
|
154
|
$c++ if $c_key =~ /$key/; |
198
|
|
|
|
|
|
|
} |
199
|
10
|
|
|
|
|
43
|
$self->explain("$c matching occurencies found\n"); |
200
|
10
|
100
|
|
|
|
45
|
next if $c > 0; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# should only get here in case of error. |
204
|
11
|
|
|
|
|
19
|
my $error_msg = ''; |
205
|
|
|
|
|
|
|
$error_msg = $self->{schema}->{$key}->{error_msg} |
206
|
11
|
100
|
|
|
|
42
|
if $self->{schema}->{$key}->{error_msg}; |
207
|
|
|
|
|
|
|
|
208
|
11
|
|
|
|
|
18
|
my $error_clause = ''; |
209
|
11
|
100
|
|
|
|
31
|
if( $error_msg ){ |
210
|
4
|
|
|
|
|
11
|
$error_clause = " Error msg: '$error_msg'"; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
11
|
|
|
|
|
44
|
$self->error("mandatory key '$key' missing.".$error_clause); |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
else{ |
216
|
1163
|
|
|
|
|
1694
|
$self->explain("false\n"); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# find key to validate (section of) data against |
222
|
|
|
|
|
|
|
sub _schema_twin_key{ |
223
|
280
|
|
|
280
|
|
594
|
my $self = shift; |
224
|
280
|
|
|
|
|
330
|
my $key = shift; |
225
|
|
|
|
|
|
|
|
226
|
280
|
|
|
|
|
331
|
my $schema_key; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# direct match: exact declaration |
229
|
280
|
100
|
|
|
|
602
|
if ($self->{schema}->{$key}){ |
230
|
181
|
|
|
|
|
347
|
$self->explain(" ok\n"); |
231
|
181
|
|
|
|
|
235
|
$schema_key = $key; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
# match against a pattern |
234
|
|
|
|
|
|
|
else { |
235
|
99
|
|
|
|
|
136
|
my $match; |
236
|
99
|
|
|
|
|
126
|
for my $match_key (keys %{$self->{schema}}){ |
|
99
|
|
|
|
|
256
|
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# only try to match a key if it has the property |
239
|
|
|
|
|
|
|
# _regex_ set |
240
|
|
|
|
|
|
|
next unless exists $self->{schema}->{$match_key} |
241
|
139
|
100
|
66
|
|
|
545
|
and $self->{schema}->{$match_key}->{regex}; |
242
|
|
|
|
|
|
|
|
243
|
97
|
100
|
|
|
|
812
|
if ($key =~ /$match_key/){ |
244
|
91
|
|
|
|
|
335
|
$self->explain("'$key' matches $match_key\n"); |
245
|
91
|
|
|
|
|
182
|
$schema_key = $match_key; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# if $schema_key is still undef we were unable to |
251
|
|
|
|
|
|
|
# match it against a key in the schema. |
252
|
280
|
100
|
|
|
|
497
|
unless ($schema_key){ |
253
|
8
|
|
|
|
|
43
|
$self->explain(">>$key not in schema, keys available: "); |
254
|
8
|
|
|
|
|
16
|
$self->explain(join (", ", (keys %{$self->{schema}}))); |
|
8
|
|
|
|
|
37
|
|
255
|
8
|
|
|
|
|
24
|
$self->explain("\n"); |
256
|
8
|
|
|
|
|
26
|
$self->error("key '$key' not found in schema\n"); |
257
|
|
|
|
|
|
|
} |
258
|
280
|
|
|
|
|
621
|
return $schema_key |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# 'validator' specified gets this called to call the callback :-) |
262
|
|
|
|
|
|
|
sub __validator_returns_undef { |
263
|
272
|
|
|
272
|
|
338
|
my $self = shift; |
264
|
272
|
|
|
|
|
325
|
my $key = shift; |
265
|
272
|
|
|
|
|
324
|
my $schema_key = shift; |
266
|
272
|
100
|
|
|
|
645
|
return unless $self->{schema}->{$schema_key}->{validator}; |
267
|
137
|
|
50
|
|
|
631
|
$self->explain("running validator for '$key': ".($self->{data}->{$key} // '(undefined)').": \n"); |
268
|
|
|
|
|
|
|
|
269
|
137
|
100
|
100
|
|
|
508
|
if (ref $self->{data}->{$key} eq ref [] |
270
|
|
|
|
|
|
|
&& $self->{schema}->{$schema_key}->{array}){ |
271
|
|
|
|
|
|
|
|
272
|
3
|
|
|
|
|
5
|
my $counter = 0; |
273
|
3
|
|
|
|
|
5
|
for my $elem (@{$self->{data}{$key}}){ |
|
3
|
|
|
|
|
8
|
|
274
|
|
|
|
|
|
|
next if !defined $elem |
275
|
7
|
0
|
33
|
|
|
16
|
&& $self->{schema}{$schema_key}{allow_empty}; |
276
|
|
|
|
|
|
|
|
277
|
7
|
|
|
|
|
20
|
my $return_value = $self->{schema}{$schema_key}{validator}($elem, $self->{data}); |
278
|
7
|
100
|
|
|
|
46
|
if ($return_value){ |
279
|
3
|
|
|
|
|
21
|
$self->explain("validator error: $return_value (element $counter)\n"); |
280
|
3
|
|
|
|
|
11
|
$self->error("Execution of validator for '$key' element $counter returns with error: $return_value"); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
else { |
283
|
4
|
|
|
|
|
12
|
$self->explain("successful validation for key '$key' element $counter\n"); |
284
|
|
|
|
|
|
|
} |
285
|
7
|
|
|
|
|
25
|
$counter++; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
else { |
289
|
134
|
|
|
|
|
220
|
my $validator = $self->{schema}->{$schema_key}->{validator}; |
290
|
134
|
|
|
|
|
163
|
my $return_value; |
291
|
134
|
100
|
|
|
|
358
|
if (defined blessed $validator){ |
292
|
6
|
|
|
|
|
20
|
$return_value = $validator->validate($self->{data}{$key}); |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
else { |
295
|
128
|
|
|
|
|
380
|
$return_value = $validator->($self->{data}->{$key}, $self->{data}); |
296
|
|
|
|
|
|
|
} |
297
|
134
|
100
|
|
|
|
8793
|
if ($return_value){ |
298
|
11
|
|
|
|
|
46
|
$self->explain("validator error: $return_value\n"); |
299
|
11
|
|
|
|
|
61
|
$self->error("Execution of validator for '$key' returns with error: $return_value"); |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
else { |
302
|
123
|
|
|
|
|
313
|
$self->explain("successful validation for key '$key'\n"); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
# called by validate to check if a value is in line with definitions |
308
|
|
|
|
|
|
|
# in the schema. |
309
|
|
|
|
|
|
|
sub __value_is_valid{ |
310
|
272
|
|
|
272
|
|
329
|
my $self = shift; |
311
|
272
|
|
|
|
|
338
|
my $key = shift; |
312
|
|
|
|
|
|
|
|
313
|
272
|
100
|
100
|
|
|
983
|
if (exists $self->{schema}->{$key} |
314
|
|
|
|
|
|
|
and $self->{schema}->{$key}->{value}){ |
315
|
14
|
|
|
|
|
56
|
$self->explain('>>'.ref($self->{schema}->{$key}->{value})."\n"); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# currently, 2 type of restrictions are supported: |
318
|
|
|
|
|
|
|
# (callback) code and regex |
319
|
14
|
50
|
|
|
|
70
|
if (ref($self->{schema}->{$key}->{value}) eq 'CODE'){ |
|
|
50
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# possibly never implement this because of new "validator" |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
elsif (ref($self->{schema}->{$key}->{value}) eq 'Regexp'){ |
323
|
14
|
100
|
66
|
|
|
71
|
if (ref $self->{data}->{$key} eq ref [] |
324
|
|
|
|
|
|
|
&& $self->{schema}{$key}{array}){ |
325
|
|
|
|
|
|
|
|
326
|
1
|
|
|
|
|
3
|
for my $elem (@{$self->{data}{$key}}){ |
|
1
|
|
|
|
|
46
|
|
327
|
|
|
|
|
|
|
next if !defined $elem |
328
|
5
|
0
|
33
|
|
|
16
|
&& $self->{schema}{$key}{allow_empty}; |
329
|
|
|
|
|
|
|
|
330
|
5
|
|
|
|
|
24
|
$self->explain(">>match '$elem' against '$self->{schema}->{$key}->{value}'"); |
331
|
|
|
|
|
|
|
|
332
|
5
|
100
|
|
|
|
46
|
if ($elem =~ m/^$self->{schema}{$key}{value}$/){ |
333
|
4
|
|
|
|
|
8
|
$self->explain(" ok.\n"); |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
else{ |
336
|
|
|
|
|
|
|
# XXX never reach this? |
337
|
1
|
|
|
|
|
4
|
$self->explain(" no.\n"); |
338
|
1
|
|
|
|
|
5
|
$self->error("$elem does not match ^$self->{schema}->{$key}->{value}\$"); |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
# XXX this was introduced to support arrays. |
343
|
|
|
|
|
|
|
else { |
344
|
13
|
|
|
|
|
68
|
$self->explain(">>match '$self->{data}->{$key}' against '$self->{schema}->{$key}->{value}'"); |
345
|
|
|
|
|
|
|
|
346
|
13
|
100
|
|
|
|
239
|
if ($self->{data}->{$key} =~ m/^$self->{schema}->{$key}->{value}$/){ |
347
|
12
|
|
|
|
|
42
|
$self->explain(" ok.\n"); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
else{ |
350
|
|
|
|
|
|
|
# XXX never reach this? |
351
|
1
|
|
|
|
|
4
|
$self->explain(" no.\n"); |
352
|
1
|
|
|
|
|
5
|
$self->error("$self->{data}->{$key} does not match ^$self->{schema}->{$key}->{value}\$"); |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
else{ |
357
|
|
|
|
|
|
|
# XXX match literally? How much sense does this make?! |
358
|
|
|
|
|
|
|
# also, this is not tested |
359
|
|
|
|
|
|
|
|
360
|
0
|
|
|
|
|
|
$self->explain("neither CODE nor Regexp\n"); |
361
|
0
|
|
|
|
|
|
$self->error("'$key' not CODE nor Regexp"); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
1; |