File Coverage

blib/lib/Data/RuledValidator.pm
Criterion Covered Total %
statement 360 404 89.1
branch 166 238 69.7
condition 84 127 66.1
subroutine 56 61 91.8
pod 19 29 65.5
total 685 859 79.7


line stmt bran cond sub pod time code
1             package Data::RuledValidator;
2              
3             our $VERSION = '0.13';
4              
5 6     6   195889 use strict;
  6         15  
  6         236  
6 6     6   32 use warnings "all";
  6         12  
  6         225  
7 6     6   8500 use File::Slurp;
  6         103749  
  6         483  
8 6     6   5137 use Data::RuledValidator::Util;
  6         14  
  6         473  
9 6     6   3685 use Data::RuledValidator::Filter;
  6         12  
  6         158  
10 6     6   5335 use Class::Inspector;
  6         40260  
  6         190  
11 6     6   5155 use UNIVERSAL::require;
  6         10090  
  6         61  
12 6     6   5625 use List::MoreUtils qw/any uniq/;
  6         14295  
  6         646  
13 6     6   5618 use Module::Pluggable search_path => [qw/Data::RuledValidator::Plugin Data::RuledValidator::Filter/];
  6         79495  
  6         56  
14              
15             use overload
16 6         60 '""' => \&valid,
17 6     6   11737 '@{}' => \&_result;
  6         6971  
18              
19             my %RULES;
20             my %COND_OP;
21             my %MK_CLOSURE;
22             my %REQUIRED;
23             my %FILTER;
24              
25             sub _rules{
26 53     53   89 my($self, $rule) = @_;
27 53 50       177 if(@_ == 2){
28 53 100       163 if(exists $RULES{$rule}){
29 51         1373 my $t = (stat $rule)[9];
30 51   66     199 $RULES{$rule}->{time} ||= $t;
31 51 100       173 if($RULES{$rule}->{time} < $t){
32 2         76 delete $RULES{$rule}->{coded_rule};
33 2         6 delete $REQUIRED{$rule};
34 2         5 $RULES{$rule}->{time} = $t;
35             }
36             }
37 53   100     318 return $RULES{$rule}->{coded_rule} ||= {};
38             }else{
39 0         0 return \%RULES;
40             }
41             }
42              
43             sub id_key{
44 29     29 1 85 my($self, $rule, $id_key) = @_;
45 29 100       253 @_ == 3 ? $RULES{$rule}->{id_key} = $id_key: $RULES{$rule}->{id_key};
46             }
47              
48             sub id_method{
49 26     26 0 56 my($self, $rule, $id_method) = @_;
50 26 50 33     174 $rule ||= $self->rule or Carp::croak("first argument 'rule' is missing;");
51 26 100 66     378 @_ == 3 ? $RULES{$rule}->{id_method} = $id_method: $RULES{$rule}->{id_method} || $self->{id_method};
52             }
53              
54             sub _regex_group{
55 2     2   5 my($self, $rule, $id_name) = @_;
56 2 50       7 if(@_ == 3){
57 0   0     0 return push @{$RULES{$rule}->{_regex_group} ||= []}, $id_name;
  0         0  
58             }else{
59 2 50       3 return @{$RULES{$rule}->{_regex_group} || []}
  2         17  
60             }
61             }
62              
63             sub import{
64 6     6   72 my($class, %option) = @_;
65 6         14 my %import;
66 6   66     57 $option{plugin} ||= $option{import}; # backward comatibility
67 6         17 foreach (qw/plugin filter/){
68 12 50       70 $option{$_} = ref $option{$_} ? $option{$_} :
    100          
69             $option{$_} ? [ $option{$_} ] :
70             [] ;
71             }
72 6         15 @import{ map { __PACKAGE__ . '::Plugin::' . $_ } @{$option{plugin}}} = ();
  1         8  
  6         20  
73 6         13 @import{ map { __PACKAGE__ . '::Filter::' . $_ } @{$option{filter}}} = ();
  2         8  
  6         23  
74 6         179 foreach my $plugin (__PACKAGE__->plugins){
75 18 50       12871 unless(Class::Inspector->loaded($plugin)){
76 18 100 66     1464 if( (not @{$option{plugin}} or not @{$option{filter}} ) or exists $import{$plugin} ){
      66        
77 15         182 $plugin->require
78             }
79 18         172 delete $import{ $plugin };
80 18 50 33     74 if($@ and my $er = $option{import_error}){
81 0 0       0 if($er == 1){
82 0         0 warn "Plugin import Error: $plugin - $@";
83             }else{
84 0         0 die "Plugin import Error: $plugin - $@";
85             }
86             }
87 18 50       227 if($plugin =~/^${class}::Filter::/){
88 6     6   4518 no strict 'refs';
  6         12  
  6         35858  
89 0         0 push @{$class . '::Filter::ISA'}, $plugin;
  0         0  
90             }
91             }else{
92 0         0 delete $import{ $plugin };
93             }
94             }
95 6 100       48 unless(Class::Inspector->loaded(__PACKAGE__ . '::Plugin::Core')){
96 1         52 (__PACKAGE__ . '::Plugin::Core')->require;
97             }
98 6 100 66     160 if(( @{$option{plugin}} or @{$option{filter}} ) and %import){
      66        
99 1         1311 die join(", ", keys %import) . " plugins doesn't exist.";
100             }
101              
102             }
103              
104 79 100   79   128 sub _cond_op{ my $self = shift; return @_ ? $COND_OP{shift()} : keys %COND_OP};
  79         865  
105              
106             sub add_operator{
107 6     6 1 116 my($self, %op_sub) = @_;
108 6         51 while(my($op, $sub) = each %op_sub){
109 120 50       224 if($MK_CLOSURE{$op}){
110 0         0 Carp::croak("$op has already defined as normal operator.");
111             }
112 120         375 $MK_CLOSURE{$op} = $sub;
113             }
114             }
115              
116             sub add_condition{
117 16     16 1 95 my($self, %op_sub) = @_;
118 16         94 while(my($op, $sub) = each %op_sub){
119 64 50       148 if(defined $COND_OP{$op}){
120 0         0 Carp::croak("$op is already defined as condition operator.");
121             }
122 64         287 $COND_OP{$op} = $sub;
123             }
124             }
125              
126 16     16 0 37 sub add_condition_operator{ my $self = shift; $self->add_condition(@_); }
  16         69  
127              
128             sub create_alias_operator{
129 1     1 0 4 my($self, $alias, $original) = @_;
130 1 50       10 if($MK_CLOSURE{$alias}){
    50          
131 0         0 Carp::croak("$alias has already defined as context/normal operator.");
132             }elsif(not $MK_CLOSURE{$original}){
133 0         0 Carp::croak("$original is not defined as context/normal operator.");
134             }
135 1         5 $MK_CLOSURE{$alias} = $MK_CLOSURE{$original};
136             }
137              
138             sub create_alias_cond_operator{
139 1     1 0 4 my($self, $alias, $original) = @_;
140 1 50       8 if($COND_OP{$alias}++){
141 0         0 Carp::croak("$alias has already defined as condition operator.");
142             }
143 1         6 $COND_OP{$alias} = $COND_OP{$original};
144             }
145              
146             sub new{
147 22     22 1 1154759 my($class, %option) = @_;
148 22         68 $option{result} = {};
149 22         51 $option{valid} = 0;
150 22   100     93 $option{rule} ||= '';
151 22   100     129 $option{filter_replace} ||= 0;
152 22   50     112 $option{rule_path} ||= '';
153 22 50 33     529 if($option{rule_path} and $option{rule_path} !~m{/$}){
154 0         0 $option{rule_path} .= '/';
155             }
156 22 50       84 if(not defined $option{auto_reset}){
157 22         57 $option{auto_reset} = 1;
158             }
159 22         75 my $o = bless \%option, $class;
160 22         69 return $o;
161             }
162              
163             sub rule{
164 26     26 1 1110 my($self, $rule) = @_;
165 26 50       68 if(@_ == 2){
166 0         0 return $self->{rule} = $rule;
167             }else{
168 26         160 return $self->{rule};
169             }
170             }
171              
172             sub list_plugins{
173 0     0 1 0 my($self) = @_;
174 0         0 return $self->plugins;
175             }
176              
177 727     727 0 5607 sub obj{ shift()->{obj} };
178              
179 25     25 0 132 sub id_obj{ shift()->{id_obj} };
180              
181 0     0 0 0 sub to_obj{ shift()->{to_obj} };
182              
183 709     709 1 1687 sub method{ shift()->{method} };
184              
185             sub key_method{
186 30     30 1 49 my($self) = @_;
187 30         55 my $method = $self->{key_method};
188 30 50       100 return defined $method ? $method : $self->method;
189             };
190              
191             sub required_alias_name{
192 410     410 1 639 my($self, $name) = @_;
193 410 50       1045 if(@_ == 2){
194 0         0 return $self->{required_alias_name} = $name;
195             }else{
196 410   50     2313 return $self->{required_alias_name} || 'required';
197             }
198             }
199              
200             sub _parse_definition{
201 32     32   57 my($self, $defs) = @_;
202 32         47 my(%def, %required, %filter);
203 32         55 my($no_required, $no_filter) = (0, 0);
204 32         83 my $required_name = $self->required_alias_name;
205 32         74 foreach my $def (@$defs){
206 127 100       611 my $alias = $def =~ s/^\s*(\w+)\s*=\s*// ? $1 : '';
207 127 100 100     532 if($alias and $alias eq $required_name){
    100          
208 4 100       31 if($def =~ m{^\s*n/a\s*$}){
    50          
209 3         8 $no_required = 1;
210             }elsif(my @keys = grep $_, split /\s*,\s*/, $def){
211 1         14 @required{@keys} = ();
212             }
213             }elsif($def =~/filter\s+(.+?)\s+with\s+(.+?)\s*$/){
214 11         30 my($keys, $values) = ($1, $2);
215 11         39 my @values = grep $_, split /\s*,\s*/, $values;
216 11 50       80 if($def =~ m{^\s*n/a\s*$}){
    100          
    50          
217 0         0 $no_filter = 1;
218             }elsif($keys eq '*'){
219 2         9 $filter{'*'} = \@values;
220             }elsif(my @keys = grep $_, split /\s*,\s*/, $keys){
221 9         49 @filter{@keys} = (\@values) x @keys;
222             }
223             }else{
224 112         130 my $filter;
225 112 100       432 if($def =~ s{\s+with\s+n/a\s*$}{}){
    100          
226 1         2 $filter = [ 'no_filter' ];
227             }elsif($def =~ s/\s+with\s+(.+?)\s*$//){
228 5         23 $filter = [ grep $_, split /\s*,\s*/, $filter = $1];
229             }
230 112         347 my($key, $op, $cond) = split /\s+/, $def, 3;
231 112 50       548 my($closure, $flg) = $MK_CLOSURE{$op} ? $MK_CLOSURE{$op}->($key, $cond, $op) : Carp::croak("not defined operator: $op");
232 111   100     657 $flg ||= 0;
233 111 50 66     325 if($flg & NEED_ALIAS and not $alias){
234 0         0 Carp::croak("Rule Syntax Error: $op needs alias name.");
235             }
236 111   66     148 push @{$def{$alias || $key} ||= []}, [$alias, $key, $op, $closure, $flg, $filter];
  111   100     1324  
237             }
238             }
239 31 100       179 return(\%def, $no_required ? undef : \%required, $no_filter ? undef : \%filter);
    50          
240             }
241              
242             sub by_sentence{
243 6     6 1 28 my $given_data = {};
244 6 50       34 $given_data = pop(@_) if ref $_[-1] eq 'HASH';
245              
246 6         32 my($self, @definition) = @_;
247 6 50       28 $self->reset if $self->auto_reset;
248 6 50       24 @definition = @{$definition[0]} if ref $definition[0] eq 'ARRAY';
  0         0  
249 6         29 my($defs, $required, $filter) = $self->_parse_definition(\@definition);
250 5         28 return $self->_validator($defs, $given_data, $required, $filter);
251             }
252              
253             sub _get_value{
254 611     611   934 my($self, $last_obj, $method, $key) = @_;
255 611 100       1502 my @method = ref $method ? @$method : $method;
256 611         1935 $last_obj = $last_obj->$_ foreach (@method[0 .. ($#method - 1)]);
257 611         1398 my $m = $method[$#method];
258 611         1811 return $last_obj->$m($key);
259             }
260              
261             sub _get_key_list{
262 30     30   65 my($self, $last_obj, $method) = @_;
263 30 50       115 my @method = ref $method ? @$method : $method;
264 30         127 $last_obj = $last_obj->$_ foreach @method[0 .. ($#method - 1)];
265 30         65 my $m = $method[$#method];
266 30         123 return $last_obj->$m;
267             }
268              
269             sub _validator{
270 30     30   68 my($self, $defs, $given_data, $required, $filter) = @_;
271 30         74 my($obj, $method) = ($self->obj, $self->method);
272 30         48 my(%result, %failure, @missing);
273 30         45 my $all_result = 1;
274 30         83 my $required_valid = $self->required_alias_name . '_valid';
275 30 100 100     987 $result{$required_valid} = 1 if defined $required and %$required;
276 30         101 $self->result(\%result);
277 30         42 my @rest_defs;
278 30         65 $self->{valid} = 1;
279 30         36 my @keys;
280 30 50       79 unless(my $key_method = $self->key_method){
281 0         0 @keys = keys %$defs;
282             }else{
283 30         66 @keys = $self->_get_key_list($self->obj, $key_method)
284             }
285 30         501 my %value;
286 30   100     167 my $all_filter = $filter->{'*'} || [];
287 30         62 foreach my $key (@keys){
288 534         1287 $value{$key} = $self->_get_value_with_filter($key, $filter, $all_filter);
289             }
290 30         153 foreach my $alias (keys %$defs){
291 274         837 my $result = $self->_validate($alias, \%value, $defs, $given_data, $required, $filter, \@missing, \%failure, \%result);
292 273 50       953 $self->{valid} &= $result if defined $result;
293             }
294 29         5087 $self->missing(\@missing);
295 29         79 $self->result(\%result);
296 29         94 $self->failure(\%failure);
297 29         83 $self->_do_filter_replace;
298 29         571 return $self;
299             }
300              
301             sub _validate{
302 313     313   621 my($self, $alias, $value, $defs, $given_data, $required, $filter, $missing, $failure, $result) = @_;
303 313         799 my $validate_data = [$value, $defs, $given_data, $required, $filter, $missing, $failure, $result];
304 313         441 my $alias_result = 1;
305              
306 313         388 foreach my $def (@{$defs->{$alias}}){
  313         727  
307 322         907 my($alias, $key, $op, $sub, $flg, $here_filter) = @$def;
308 322         346 my @value;
309 322 100       906 if($here_filter){
    100          
310 17         25 @value = @{$self->_get_value_with_filter($key, undef, undef, $here_filter)};
  17         39  
311             }elsif($value->{$key}){
312 268 50       303 @value = @{$value->{$key} || []};
  268         899  
313             }else{
314 37         47 @value = @{$self->_get_value_with_filter($key, $filter, $filter->{'*'}, $here_filter)};
  37         135  
315             }
316 322 100       1203 carp::croak('cannot define same combination of key/alias and operator twice.') if exists $result->{$alias . '_' . $op};
317 321         705 my $required_valid = $self->required_alias_name . '_valid';
318 321   66     1109 $alias ||= $key;
319 321         395 my $r = undef;
320 321 50       820 if(defined $MK_CLOSURE{$op}){
321 321 100 100 299   924 if($flg & ALLOW_NO_VALUE or any sub{defined $_}, @value){
  299         1005  
322 283   100     958 $alias_result &= $r = $sub->($self, \@value, $alias, $given_data, $validate_data ) || 0;
323 283         1416 $result->{ $alias . '_' . $op } = $r;
324 283   100     1135 ($result->{ $alias . '_valid' } ||= 1) &= $r;
325 283 100 100     2462 if(not $r and @value and not defined $failure->{$alias . '_' . $op}){
      100        
326 22         134 $failure->{$alias . '_' . $op} = \@value;
327             }
328             }else{
329 38 100       98 if(exists $required->{$alias}){
330 4         8 $result->{$required_valid} &= 0;
331             }
332 38         179 push @$missing, $alias;
333             }
334             }
335             }
336 312         930 return $alias_result;
337             }
338              
339             sub _get_value_with_filter{
340 588     588   1133 my($self, $key, $filter, $all_filter, $here_filter) = @_;
341 588         1073 my @value;
342 588         1175 my($obj, $method) = ($self->obj, $self->method);
343 588 100 100     1243 if(ref $here_filter eq 'ARRAY'){
  571 100       3827  
    100          
344 17         42 @value = $self->_get_value($obj, $method, $key);
345 17         155 $self->_filter_value($key, \@value, $here_filter);
346             }elsif(@{$all_filter || []} or my $key_filter = $filter->{$key}){
347 81 100       136 unless(@value = @{ $self->_filtered_value($key) || [] }){
  81 100       165  
348 79         198 @value = $self->_get_value($obj, $method, $key);
349 79         960 $self->_filter_value($key, \@value, $key_filter, $all_filter);
350 79         253 $self->_filtered_value($key, \@value);
351             }
352             }else{
353 490         1000 @value = $self->_get_value($obj, $method, $key);
354             }
355 588         5608 return \@value;
356             }
357              
358             sub filter_replace{
359 30     30 1 568 my($self, $value) = @_;
360 30 100       93 return $self->{filter_replace} = $value if @_ == 2;
361 29         116 return $self->{filter_replace};
362             }
363              
364             sub rule_path{
365 4     4 1 10 my($self, $value) = @_;
366 4 50       15 return $self->{rule_path} = $value if @_ == 2;
367 4         38 return $self->{rule_path};
368             }
369              
370             sub auto_reset{
371 31     31 1 58 my($self, $value) = @_;
372 31 50       100 return $self->{auto_reset} = $value if @_ == 2;
373 31         240 return $self->{auto_reset};
374             }
375              
376             sub _do_filter_replace{
377 29     29   47 my($self) = @_;
378 29 100       215 return unless my $filter = $self->filter_replace;
379              
380 1 50       2 my %filter_replace = %{$self->{filtered_value} || {}};
  1         7  
381 1         11 my($obj, $method) = ($self->obj, $self->method);
382 1 50       5 if(ref $filter){
383 0         0 while(my($k, $v) = each %filter_replace){
384 0         0 $obj->$method($k, $v);
385             }
386             }else{
387 1         6 while(my($k, $v) = each %filter_replace){
388 1         5 $obj->$method($k, @$v);
389             }
390             }
391             }
392              
393             sub _filtered_value{
394 160     160   240 my($self, $key, $value) = @_;
395 160 100       578 return $self->{filtered_value}->{$key} = $value if @_ == 3;
396 81         536 return $self->{filtered_value}->{$key};
397             }
398              
399             sub _filter_value{
400 96     96   164 my($self, $key, $values, $key_filter, $all_filter) = @_;
401 96         159 foreach my $value (@$values){
402 116 100       234 $value = '' if not defined $value;
403 116         202 foreach my $filter (@$key_filter, @$all_filter){
404 116         426 Data::RuledValidator::Filter->$filter(\$value, $self, $values);
405             }
406             }
407             }
408              
409             sub result{
410 59     59 1 99 my($self, $result) = @_;
411 59 50       425 $self->{result} = $result if @_ == 2;
412 59   50     189 return($self->{result} ||= {});
413             }
414              
415             sub failure{
416 56     56 1 92 my($self, $failure) = @_;
417 56 100       166 $self->{failure} = $failure if @_ == 2;
418 56   50     208 return($self->{failure} || {});
419             }
420              
421             #sub right{
422             # my($self, $right) = @_;
423             ## $self->{right} = $right if @_ == 2;
424             # return($self->{right} || {});
425             #}
426              
427             #sub wrong{
428             # my($self, $right) = @_;
429             ## $self->{right} = $right if @_ == 2;
430             # return($self->{wrong} || {});
431             #}
432              
433             sub _result{
434 0     0   0 my($self) = @_;
435 0         0 return [%{$self->{result}}];
  0         0  
436             }
437              
438             sub missing{
439 29     29 1 48 my($self, $missing) = @_;
440 29 50       107 if(@_ == 2){
441 29         219 $self->{missing} = [ uniq @$missing ];
442             }
443 29         88 return $self->{missing};
444             }
445              
446             sub valid{
447 29     29 1 400 my($self, $valid) = @_;
448 29 50       110 if(defined $valid){
449 0         0 $self->{valid} = $valid;
450             }
451 29 100       94 if(exists $self->{valid}){
452 27         82 my $required_valid = $self->required_alias_name . '_valid';
453 27 50       93 my $not_fail = exists $self->{failure} ? not %{$self->failure} : 1;
  27         69  
454 27 50       99 if(exists $self->{result}->{$required_valid}){
455 0 0       0 return $self->ok($required_valid) ? $not_fail : 0;
456             }else{
457 27         137 return $not_fail;
458             }
459             }else{
460 2         12 return;
461             }
462             }
463              
464             sub reset{
465 33     33 1 59 my($self) = @_;
466 33         357 delete $self->{$_} foreach qw/result valid failure filtered_value right wrong/;
467             }
468              
469             sub by_rule{
470 25     25 1 119 my $given_data = {};
471 25 100       114 $given_data = pop(@_) if ref $_[-1] eq 'HASH';
472 25         55 my($self, $rule, $group_name) = @_;
473              
474 25 50       137 $self->reset if $self->auto_reset;
475 25 50       160 $rule = $rule ? $self->rule($rule) : $self->rule;
476 25 50       1194 Carp::croak("need rule name") unless $rule;
477 25 50       38 $self->_parse_rule($rule) unless %{ $self->_rules($rule) || {} };
  25 100       282  
478 25   33     97 my($obj, $method) = ($self->id_obj || $self->obj, $self->id_method($rule) || $self->method);
      66        
479              
480 25 50       70 unless($group_name){
481 25         143 my $id_key = $self->id_key($rule);
482 25 50 33     171 $group_name = $id_key =~ /^ENV_(.+)$/i ? $ENV{uc($1)} : $self->_get_value($obj, $method, $id_key || ());
483             }
484 25 100       280 my $defs = defined $group_name ? $self->_rules($rule)->{$group_name} : undef;
485              
486 25 100       71 unless($defs){
487 2         7 foreach my $r ($self->_regex_group($rule)){
488 0 0       0 last if $defs = $self->_rules($rule)->{$r};
489             }
490             }
491 25         65 $self->{group_name} = $group_name;
492 25 100 100     236 return $self->_validator($defs || {}, $given_data, $group_name ? ($REQUIRED{$group_name}, $FILTER{$group_name}) : ());
493             }
494              
495             sub _merge_rule{
496 22     22   36 my($self, $global_rule, $rule) = @_;
497 22         25 my %has;
498             my %na;
499 0         0 my %new_rule;
500 0         0 my %rule;
501 22         31 my $global_is_na = 0;
502              
503 22 100       68 if(my $rule_global = $rule->{GLOBAL}){
504 9         14 foreach my $def (@$rule_global){
505 9 50 33     84 if( ref $def eq 'ARRAY'
      33        
      33        
506             and $def->[1] eq 'GLOBAL'
507             and $def->[2] eq 'is'
508             and $def->[3] eq 'n/a'
509             ){
510 9         33 %rule = %$rule;
511 9         28 $global_is_na = 1;
512             }
513             }
514             }
515 22 100       60 unless($global_is_na){
516 13         92 %rule = %$global_rule;
517 13         69 @rule{keys %$rule} = values %$rule;
518             }
519              
520 22         67 foreach my $alias (keys %rule){
521 166         169 my @new_rule;
522 166         166 foreach my $def (@{$rule{$alias}}){
  166         291  
523 174 50       439 next unless $def->[2];
524 174         305 my($alias, $key, $op, $cond) = @$def;
525 174   66     566 $alias = $alias || $key;
526 174 50       332 if(exists $MK_CLOSURE{$op}){
527 174 100       438 $na{$alias}->{$op} = 1 if $cond eq 'n/a';
528 174 100 66     1659 push @new_rule, $def unless $na{$alias}->{$op} or $has{$alias}->{$op}++;
529             }else{
530 0         0 push @new_rule, $def;
531             }
532             }
533 166         451 $new_rule{$alias} = \@new_rule;
534             }
535             # $Data::Dumper::Deparse = 1;
536             # warn Data::Dumper::Dumper($new_rule{mail3});
537 22         214 return \%new_rule, $global_is_na;
538             }
539              
540             sub _merge_filter{
541 22     22   38 my($self, $filter, $global_filter) = @_;
542 22         82 while(my($k, $v) = each %$global_filter){
543 8 50       39 $filter->{$k} = $v if not exists $filter->{$k};
544             }
545 22         196 return $filter;
546             }
547              
548             sub _parse_rule{
549 4     4   9 my($self, $rule) = @_;
550 4         12 my $rules = $self->_rules($rule);
551 4         9 my $id_name = 'GLOBAL';
552 4         10 my @rule;
553 4 50       25 if(ref $rule eq 'SCALAR'){
554 0         0 @rule = split/[\n\r]/, $$rule;
555             }else{
556 4 50       20 @rule = File::Slurp::read_file($self->rule_path . $rule)
557             or Carp::croak "cannot open $rule";
558             }
559 4         1146 foreach(@rule){
560 199         354 chomp;
561 199         278 my $line = $_;
562 199         298 $line =~s/^\s+//;
563 199         557 $line =~s/\s+$//;
564 199 100 100     870 next unless $line and $line !~ /^\s*#/;
565 124         152 my $is_regex = 0;
566 124 50 33     908 if($line =~ s/^;+path;+/;/ or $line =~ s/path\{/\{/){
    50 33        
567 0         0 $is_regex = 1;
568 0         0 $line =~ s{/+$}{};
569 0         0 $line = '^'. $line . '/?$';
570             }elsif($line =~ s/^;+r;+/;/ or $line =~ s/r\{/\{/){
571 0         0 $is_regex = 1;
572             }
573 124 100 66     833 if($line =~s/^ID_KEY\s+//i){
    100          
    100          
574 4         20 $self->id_key($rule, $line);
575             }elsif($line =~s/^ID_METHOD\s+//i){
576 1         8 my @method = grep $_, split /\s*,\s*/, $line;
577 1         5 $self->id_method($rule, \@method);
578             }elsif($line =~/^\s*\{\s*([^\s]+)\s*\}\s*$/ or $line =~m|^\s*;+\s*([^\s]+)\s*$|){
579             # page name
580 26         60 $id_name = $1;
581 26   50     151 $rules->{$id_name} ||= [];
582 26 50       198 $self->_regex_group($rule, $id_name) if $is_regex;
583             }else{
584             # rule
585 93         105 push @{$rules->{$id_name}}, $line;
  93         978  
586             }
587             }
588 4         29 my($global_rule, $required, $filter) = $self->_parse_definition($rules->{GLOBAL});
589              
590 4   50     20 $rules->{ GLOBAL } = $global_rule ||= [];
591 4         16 $REQUIRED{ GLOBAL } = $required;
592 4         10 $FILTER{ GLOBAL } = $filter;
593 4         29 while(my($id_name, $defs) = each %$rules){
594 26 100       80 next if $id_name eq 'GLOBAL';
595 22         61 my($rule, $required, $filter) = $self->_parse_definition($defs);
596              
597 22         47 my $global_is_na;
598 22   50     106 ($rules->{$id_name}, $global_is_na) = $self->_merge_rule($global_rule, $rule ||= {});
599 22 100       65 if(defined $required){
600 19 100       78 $REQUIRED{$id_name} = %$required ? $required : $global_is_na ? {} : $REQUIRED{GLOBAL};
    50          
601             }
602 22 50       60 if(defined $filter){
603 22 100       141 $FILTER{$id_name} = $self->_merge_filter($filter, $global_is_na ? {} : $FILTER{GLOBAL});
604             }
605             }
606             }
607              
608 47     47 0 2209 sub ok{ return shift()->{result}->{shift()} }
609              
610 65     65 0 297 sub valid_ok{ return shift()->{result}->{shift() . '_valid'} }
611              
612             sub valid_yet{
613 65     65 0 102 my($self, $alias) = @_;
614 65 100       256 return 0 if exists $self->{result}->{$alias . '_valid'};
615 39         129 return 1;
616             }
617              
618             sub __condition{
619 0     0     my($self, $name, $func) = @_;
620             return
621 0 0         @_ == 3 ? $COND_OP{$name} = $func :
    0          
622             exists $COND_OP{$name} ? $COND_OP{$name} :
623             Carp::croak( $name . ' is not defined condition name');
624             }
625              
626             sub __operator{
627 0     0     my($self, $name, $func) = @_;
628             return
629 0 0         @_ == 3 ? $MK_CLOSURE{$name} = $func :
    0          
630             exists $MK_CLOSURE{$name} ? $MK_CLOSURE{$name} :
631             Carp::croak( $name . ' is not defined operator name');
632             }
633              
634 6     6   4780 use Data::RuledValidator::Closure;
  6         16  
  6         91  
635              
636             1;
637              
638             =head1 NAME
639              
640             Data::RuledValidator - data validator with rule
641              
642             =head1 DESCRIPTION
643              
644             Data::RuledValidator is validator of data.
645             This needs rule which is readable by not programmer ... so it is like specification.
646              
647             =head1 WHAT FOR ?
648              
649             One programmer said;
650              
651             specification is in code, so documentation is not needed.
652              
653             Another programmer said;
654              
655             code is specification, so if I write specification, it is against DRY.
656              
657             It is excuse of them. They may dislike to write documents, they may be not good at writing documents,
658             and/or they may think validation check is trivial task.
659             But, if specification is used by programming and we needn't write program,
660             they will start to write specification. And, at last, we need specification.
661              
662             =head1 SYNOPSIS
663              
664             You can use this without rule file.
665              
666             BEGIN{
667             $ENV{REQUEST_METHOD} = "GET";
668             $ENV{QUERY_STRING} = "page=index&i=9&k=aaaaa&v=bbbb";
669             }
670            
671             use Data::RuledValidator;
672              
673             use CGI;
674            
675             my $v = Data::RuledValidator->new(obj => CGI->new, method => "param");
676             print $v->by_sentence("age is num", "name is word", "nickname is word", "required = age,name,nickname"); # return 1 if valid
677              
678             This means that parameter of CGI object, age is number, name is word,
679             nickname is also word and require age, name and nickname.
680              
681             Next example is using following rule in file "validator.rule";
682              
683             ;;GLOBAL
684              
685             ID_KEY page
686            
687             # $cgi->param('age') is num
688             age is num
689             # $cgi->param('name') is word
690             name is word
691             # $cgi->param('nickname') is word
692             nickname is word
693            
694             # following rule is applyed when $cgi->param('page') is 'index'
695             ;;index
696             # requied $cgi->param('age'), $cgi->param('name') and $cgi->param('nickname')
697             required = age, name, nickname
698              
699             And code is(environmental values are as same as first example):
700              
701             my $v = Data::RuledValidator->new(obj => CGI->new, method => "param", rule => "validator.rule");
702             print $v->by_rule; # return 1 if valid
703              
704             This is as nearly same as first example.
705             left value of ID_KEY, "page" is parameter name to specify rule name to use.
706              
707             my $q = CGI->new;
708             $id = $q->param("page");
709              
710             Now, $id is "index" (see above environmental values in BEGIN block),
711             use rule in "index". The specified module and method in new is used.
712             "index" rule is following:
713              
714             ;;index
715             required = age, name, nickname
716              
717             Global rule is applied as well.
718              
719             age is num
720             name is word
721             nickname is word
722              
723             So it is as same as first example.
724             This means that parameter of CGI object, age is number, name is word,
725             nickname is also word and require age, name and nickname.
726              
727             =head1 RuledValidator GENERAL IDEA
728              
729             =over 4
730              
731             =item * Object
732              
733             Object has data which you want to check
734             and Object has Method which returns Value(s) from Object's data.
735              
736             =item * Key
737              
738             Basically, Key is the key which is passed to Object Method.
739              
740             =item * Value(s)
741              
742             Value(s) are the returned of the Object Method passed Key.
743              
744             =item * Operator
745              
746             Operator is operator to check Value(s).
747              
748             =item * Condition
749              
750             Condition is the condition for Operator
751             to judge whether Value(s) is/are valid or not.
752              
753             =back
754              
755             =head1 USING OPTION
756              
757             When using Data::RuledValidator, you can use option.
758              
759             =over 4
760              
761             =item import_error
762              
763             This defines behavior when plugin is not imported correctly.
764              
765             use Data::RuledValidator import_error => 0;
766              
767             If value is 0, do nothing. It is default.
768              
769             use Data::RuledValidator import_error => 1;
770              
771             If value is 1, warn.
772              
773             use Data::RuledValidator import_error => 2;
774              
775             If value is 2, die.
776              
777             =item plugin
778              
779             You can specify which plugins you want to load.
780              
781             use Data::RuledValdiator plugin => [qw/Email/];
782              
783             If you don't specify any plugins, all plugins will be loaded.
784              
785             =item filter
786              
787             You can specify which filter plugins you want to load.
788              
789             use Data::RuledValdiator filter => [qw/XXX/];
790              
791             If you don't specify any filter plugins, all filter plugins will be loaded.
792              
793             =back
794              
795             =head1 CONSTRUCTOR
796              
797             =over 4
798              
799             =item new
800              
801             my $v = Data::RuledValidator->new(
802             obj => $obj,
803             method => $method,
804             rule => $rule_file_location,
805             );
806              
807             $obj is Object which has values which you want to check.
808             $method is Method of $obj which returns Value(s) which you want to check.
809             $rule_file_location is file location of rule file.
810              
811             my $v = Data::RuledValidator->new(obj => $obj, method => $method);
812              
813             If you use "by_sentence" and/or you use "by_rule" with argument, no need to specify rule here.
814              
815             You can use array ref for method. for example, $c is object, and $c->res->param is the way to get values.
816             pass [qw/res param/] to method.
817              
818             If you need another object and/or method for identify to group name.
819              
820             my $v = Data::RuledValidator->new(obj => $obj, method => $method, id_obj => $id_obj, id_method => $id_method);
821              
822             for validation, $obj->$method is used.
823             for identifying to group name, $id_obj->$id_method is used (when you omit id_method, method is used).
824              
825             =back
826              
827             =head2 CONSTRUCTOR OPTION
828              
829             =over 4
830              
831             =item rule
832              
833             rule => rule_file_location
834              
835             explained above.
836              
837             =item filter_replace
838              
839             Data::RuledValidator has filter feature.
840             You can decide replace object method value with filtered value or not.
841              
842             This option can take 3 kind of value.
843              
844             filter_replace => 0
845              
846             This will not use filtered value.
847              
848             filter_replace => 1
849             filter_replace => []
850              
851             Use filtered value.
852             Using 1 or [] is depends on the way to set value with object method.
853              
854             1 ... $q->param(key, @value);
855             [] ... $q->param(key, [ @value ]);
856              
857             =item rule_path
858              
859             rule_path => '/path/to/rule_dir/'
860              
861             You can specify the path of the directory including rule files.
862              
863             =item auto_reset
864              
865             By default, reset method is automatically called
866             when by_rule or by_sentence is called.
867              
868             If you want to change this behavior, set it.
869              
870             auto_reset => 0
871              
872             You can change the value by method auto_reset.
873              
874             =item key_method
875              
876             key_method => 'param'
877              
878             key_method is the method of C which returns keys like as I of CGI module.
879             If you don't specify this value, the value you specified as C is used.
880             if you want to disable this, set 0 or empty value as following.
881              
882             key_method => 0
883             key_method => ''
884              
885             This is for I<"filter * with ..."> sentence in L and when C is true,
886             this filter sentence apply filter all values of keys which are returned by C.
887             When you disable this(you set key_method => 0), the values applyed filter are only keys which are in rule.
888              
889             =back
890              
891             =head1 METHOD for VALIDATION
892              
893             =over 4
894              
895             =item by_sentence
896              
897             $v->by_sentence("i is number", "k is word", ...);
898              
899             The arguments is rule. You can write multiple sentence.
900             It returns $v object.
901              
902             =item by_rule
903              
904             $v->by_rule();
905             $v->by_rule($rule_file);
906             $v->by_rule($rule_file, $group_name);
907              
908             If $rule is omitted, using the file which is specified in new.
909             It returns $v object.
910              
911             =item result
912              
913             $v->result;
914              
915             The result of validation check.
916             This returned the following structure.
917              
918             {
919             'i_is' => 0,
920             'v_is' => 0,
921             'z_match' => 1,
922             }
923              
924             This means
925              
926             key 'i' is invalid.
927             key 'v' is invalid.
928             key 'z' is valid.
929              
930             You can get this result as following:
931              
932             %result = @$v;
933              
934             =item valid
935              
936             $v->valid;
937              
938             The result of total validation check.
939             The returned value is 1 or 0.
940              
941             You can get this result as following, too:
942              
943             $result = $v;
944              
945             =item failure
946              
947             $v->failure;
948              
949             Given values to validation check.
950             Some/All of them are wrong value.
951             This returned, for example, the following structure.
952              
953             {
954             'i_is' => ['x', 'y', 'z'],
955             'v_is' => ['x@x.jp'],
956             'z_match' => [0123, 1234],
957             }
958              
959             If you want wrong value only, use wrong method.
960              
961             =item missing
962              
963             The values included in rule is not given from object.
964             You can get such keys/aliases as following
965              
966             my $missing_arrayref = $v->missing;
967              
968             $missing_arrayref likes as following;
969              
970             ['key', 'alias']
971              
972             =item wrong
973              
974             This is not implemented.
975              
976             $v->wrong;
977              
978             It returns only wrong value.
979              
980             {
981             'i_is' => ['x', 'y', 'z'],
982             'v_is' => ['x@x.jp'],
983             'z_match' => [0123, 1234],
984             }
985              
986             All of them are wrong values.
987              
988             =item reset
989              
990             $v->reset();
991              
992             The result of validation check is reseted.
993             This is internally called when by_sentence or by_rule is called.
994              
995             =back
996              
997             =head1 OTHER METHOD
998              
999             =over 4
1000              
1001             =item required_alias_name
1002              
1003             $v->required_alias_name
1004              
1005             It is special alias name to specify required keys.
1006              
1007             =item list_plugins
1008              
1009             $v->list_plugins;
1010              
1011             list all plugins.
1012              
1013             =item filter_replace
1014              
1015             $v->filter_replace;
1016              
1017             This get/set new's option filter_replace.
1018             get/set value is 0, 1 or [].
1019              
1020             See L.
1021              
1022             =item rule_path
1023              
1024             $v->rule_path
1025              
1026             This get/set new's option rule_path.
1027              
1028             See L.
1029              
1030             =item auto_reset
1031              
1032             $v->auto_reset;
1033              
1034             This get/set new's option auto_reset.
1035             get/set value is 0, 1.
1036              
1037             See L.
1038              
1039             =back
1040              
1041             =head1 RULE SYNTAX
1042              
1043             Rule Syntax is very simple.
1044              
1045             =over 4
1046              
1047             =item ID_KEY Key
1048              
1049             The right value is key which is passed to Object->Method.
1050             The returned value of Object->Method(Key) is used to identify GROUP_NAME
1051              
1052             ID_KEY page
1053              
1054             =item ID_METHOD method, method ...
1055              
1056             Note that: It is used, only when you need another method to identify to GROUP_NAME.
1057              
1058             The right value is method which is used when Object->Method.
1059             The returned value of Object->Method(Key)/Object->Method (Key is omitted)
1060             is used to identify GROUP_NAME.
1061              
1062             ID_METHOD request action
1063              
1064             This can be defined in constructor, new.
1065              
1066             =item ;GROUP_NAME
1067              
1068             start from ; is start of group and the end of this group is the line before next ';'.
1069             If the value of Object->Method(ID_KEY) is equal GROUP_NAME, this group validation rule is used.
1070              
1071             ;index
1072              
1073             You can write as following.
1074              
1075             ;;;;index
1076              
1077             You can repeat ';' any times.
1078              
1079             =item ;r;^GROUP_NAME$
1080              
1081             This is start of group, too.
1082             If the value of Object->Method(ID_KEY) is match regexp ^GROUP_NAME$, this group validation rule is used.
1083              
1084             ;r;^.*_confirm$
1085              
1086             You can write as following.
1087              
1088             ;;r;;^.*_confirm$
1089              
1090             You can repeat ';' any times.
1091              
1092             =item ;path;/path/to/where
1093              
1094             It is as same as ;r;^/path/to/where/?$.
1095              
1096             Note that: this is needed that ID_KEY is 'ENV_PATH_INFO'.
1097              
1098             You can write as following.
1099              
1100             ;;path;;/path/to/where
1101              
1102             You can repeat ';' any times.
1103              
1104             =item ;GLOBAL
1105              
1106             This is start of group, too. but 'GLOBAL' is special name.
1107             The rule in this group is inherited by all group.
1108              
1109             ;GLOBAL
1110            
1111             i is number
1112             w is word
1113              
1114             If you write global rule on the top of rule.
1115             no need specify ;GLOBAL, they are parsed as GLOBAL.
1116              
1117             # The top of file
1118            
1119             i is number
1120             w is word
1121              
1122             They will be regarded as global rule.
1123              
1124             =item #
1125              
1126             start from # is comment.
1127              
1128             # This is comment
1129              
1130             =item sentence
1131              
1132             i is number
1133              
1134             sentence has 3 parts, at least.
1135              
1136             Key Operator Condition
1137              
1138             In example, 'i' is Key, 'is' is Operator and 'number' is Condition.
1139              
1140             This means:
1141              
1142             return $obj->$method('i') =~/^\d+$/ + 0;
1143              
1144             In some case, Operator can take multiple Condition.
1145             It is depends on Operator implementation.
1146              
1147             For example, Operator 'match' can multiple Condition.
1148              
1149             i match ^[a-z]+$,^[0-9]+$
1150              
1151             When i is match former or later, it is valid.
1152              
1153             Note that:
1154              
1155             You CANNOT use same key with same operator.
1156              
1157             i is number
1158             i is word
1159              
1160             =item alias = sentence
1161              
1162             sentence is as same as above.
1163             'alias =' effects result data structure.
1164              
1165             First example is normal version.
1166              
1167             Rule:
1168              
1169             i is number
1170             p is word
1171             z match ^\d{3}$
1172              
1173             Result Data Structure:
1174              
1175             {
1176             'i_is' => 0,
1177             'p_is' => 0,
1178             'z_match' => 1,
1179             }
1180              
1181             Next example is version using alias.
1182              
1183             id = i is number
1184             password = p is word
1185             zip = z match ^\d{3}$
1186              
1187             Result Data Structure:
1188              
1189             {
1190             'id_is' => 0,
1191             'password_is' => 0,
1192             'zip_match' => 1,
1193             }
1194              
1195             =item Special alias name for required values
1196              
1197             required = name, id, password
1198              
1199             This alias name "required" is special name and
1200             syntax after the name, is special a bit.
1201              
1202             This sentence means these keys/aliases, name, id and password are required.
1203              
1204             You can change the name "required" by required_alias_name method.
1205              
1206             Note that: You cannot write key name if you use alias and don't use the key name elsewhere.
1207              
1208             for example;
1209              
1210             foo is alpha
1211             alias = var is 'value'
1212            
1213             # It doesn't work correctly because alias is used instead of key name 'var'
1214             required = foo, var
1215              
1216             You should write as following;
1217              
1218             foo is alpha
1219             alias = var is 'value'
1220            
1221             # It works correctly because alias is used
1222             required = foo, alias
1223              
1224             But the following works correctly;
1225              
1226             foo is alpha
1227             alias = foo eq 'value'
1228            
1229             # It works correctly because key name 'foo' is used elsewhere.
1230             required = foo
1231              
1232             =item Override Global Rule
1233              
1234             You can override global rule.
1235              
1236             ;GLOBAL
1237            
1238             ID_KEY page
1239            
1240             i is number
1241             w is word
1242            
1243             ;index
1244            
1245             i is word
1246             w is number
1247              
1248             If you want delete some rules in GLOBAL in 'index' group.
1249              
1250             ;index
1251            
1252             w is n/a
1253             w match ^[e-z]+$
1254              
1255             If you want delete all GLOBAL rule in 'index' group.
1256              
1257             ;index
1258              
1259             GLOBAL is n/a
1260              
1261             =back
1262              
1263             =head1 FILTERS
1264              
1265             Data::RuledValidator has filtering feature.
1266             There are two ways how to filter values.
1267              
1268             =over 4
1269              
1270             =item filter Key, ... with FilterName, ...
1271              
1272             filter tel_number with no_dash
1273             tel_number is num
1274             tel_number length 9
1275              
1276             This declaration is no relation with location.
1277             So, following is as same mean as above.
1278              
1279             tel_number is num
1280             tel_number length 9
1281             filter tel_number with no_dash
1282              
1283             Filter is also inherited from GLOBAL.
1284             If you want to ignore GLOBAL filter, do as following;
1285              
1286             filter tel_number with n/a
1287              
1288             If you want to ignore GLOBAL filter on all keys, do as following;
1289             (not yet implemented)
1290              
1291             filter * with n/a
1292              
1293             =item Keys Operator Condition with FilterName, ...
1294              
1295             This is temporary filter.
1296              
1297             tel1 = tel_number is num with no_dash
1298             tel2 = tel_number is num
1299              
1300             tel1's tel_number is filtered tel_number,
1301             but tel2's tel_number is not filtered.
1302              
1303             But in following case, tel2 is filtered, too.
1304              
1305             filter tel_number with no_dash
1306             tel1 = tel_number is num with no_dash
1307             tel2 = tel_number is num
1308              
1309             If you want ignore "filter tel_number with no_dash",
1310             use no_filter in temporary filter.
1311              
1312             filter tel_number with no_dash
1313             tel1 = tel_number is num with no_filter
1314             tel2 = tel_number is num
1315              
1316             If temporary filter is defined, it is prior to "filter ... with ...".
1317              
1318             See also L
1319              
1320             =back
1321              
1322             =head1 OPERATORS
1323              
1324             =over 4
1325              
1326             =item is
1327              
1328             key is mail
1329             key is word
1330             key is num
1331              
1332             'is' is something special operator.
1333             It can be to be unavailable GLOBAL at all or about some key.
1334              
1335             ;;GLOBAL
1336             i is num
1337             k is value
1338              
1339             ;;index
1340             v is word
1341              
1342             in this rule, 'index' inherits GLOBAL.
1343             If you want not to use GLOBAL.
1344              
1345             ;;index
1346             GLOBAL is n/a
1347             v is word
1348              
1349             if you want not to use key 'k' in index.
1350              
1351             ;;index
1352             k is n/a
1353             v is word
1354              
1355             This inherits 'i', but doesn't inherit 'k'.
1356              
1357             =item isnt
1358              
1359             It is the opposite of 'is'.
1360             but, no use to use 'n/a' in condition.
1361              
1362             =item of
1363              
1364             This is some different from others.
1365             Left word is not key. number or 'all' and this needs alias.
1366              
1367             all = all of x,y,z
1368              
1369             This is needed all of keys x, y and z.
1370             It is no need for these value of keys to be valid.
1371             If this key exists, it is OK.
1372              
1373             If you need only 2 of these keys. you can write;
1374              
1375             2ofxyz = 2 of x,y,z
1376              
1377             This is needed 2 of keys x, y or z.
1378              
1379             If you want valid values, use of-valid instead of valid.
1380              
1381             =item of-valid
1382              
1383             This likes 'of'.
1384              
1385             all = all of-valid x,y,z
1386              
1387             This is needed all of keys x, y and z.
1388             It is needed for these value of keys to be valid.
1389              
1390             If you need only 2 of these keys. you can write;
1391              
1392             2ofvalidxyz = 2 of-valid x,y,z
1393              
1394             This is needed 2 of keys x, y or z.
1395              
1396             If you want valid values, use of-valid instead of 'of'.
1397              
1398             =item in
1399              
1400             If value is in the words, it is OK.
1401              
1402             key in Perl, Python, Ruby, PHP ...
1403              
1404             This is "or" condition. If value is equal to one of them, it is OK.
1405              
1406             =item match
1407              
1408             This is regular expression.
1409              
1410             key match ^[a-z]{2}\d{5}$
1411              
1412             If you want multiple regular expression.
1413              
1414             key match ^[a-z]{2}\d{5}$, ^\d{5}[a-z]{1}\d{5}$, ...
1415              
1416             This is "or" condition. If value is match one of them, it is OK.
1417              
1418             =item re
1419              
1420             It is as same as 'match'.
1421              
1422             =item has
1423              
1424             key has 3
1425              
1426             This means key has 3 values.
1427              
1428             If you want less than the number or grater than the number.
1429             You can write;
1430              
1431             key has < 4
1432             key has > 4
1433              
1434             =item eq (= equal)
1435              
1436             key eq STRING
1437              
1438             If key's value is as same as STRING, it is valid.
1439              
1440             You can use special string like following.
1441              
1442             key eq [key_name]
1443             key eq {data_key_name}
1444              
1445             [key_name] is result of $obj->$method(key_name).
1446             For the case which user have to input password twice,
1447             you can write following rule.
1448              
1449             password eq [password2]
1450              
1451             This rule means, for example;
1452              
1453             $cgi->param('password') eq $cgi->param('password2');
1454              
1455             {data_key_name} is result of $data->{data_key_name}.
1456             For the case when you should check data from database.
1457              
1458             my $db_data = ....;
1459             if($cgi->param('key') ne $db_data){
1460             # wrong!
1461             }
1462              
1463             In such a case, you can write as following.
1464              
1465             rule;
1466              
1467             key eq {db_data}
1468              
1469             code;
1470              
1471             my $db_data = ...;
1472             $v->by_rule({db_data => $db_data});
1473              
1474             =item ne (= not_equal)
1475              
1476             key ne STRING
1477              
1478             If key's value is NOT as same as STRING, it is valid.
1479             You can use special string like "eq" in above explanation.
1480              
1481             =item length #,#
1482              
1483             words length 0, 10
1484              
1485             If the length of words is from 0 to 10, it is valid.
1486             The first number is min length, and the second number is max length.
1487              
1488             You can write only one value.
1489              
1490             words length 5
1491              
1492             This means the length of words is lesser than 6.
1493              
1494             Note that: use it instead of '>= ~ #', '<= ~ #' and 'between ~ #, #'.
1495              
1496             =item E, E=
1497              
1498             key > 4
1499              
1500             If key's value is greater than number 4, it is valid.
1501             You can use '>=', too.
1502              
1503             If you want to check length of the value,
1504             put '~' before number as following.
1505              
1506             key > ~ 4
1507              
1508             Note that: use C, instead of '>= ~ #'.
1509              
1510             =item E, E=
1511              
1512             key < 5
1513              
1514             If key's value is less than number 5, it is valid.
1515             You can use '<=', too.
1516              
1517             If you want to check length of the value,
1518             put '~' before number as following.
1519              
1520             key < ~ 4
1521              
1522             Note that: use C, instead of '<= ~ #'.
1523              
1524             =item between #,#
1525              
1526             key between 3,5
1527              
1528             If key's value is in the range, it is valid.
1529              
1530             If you want to check length of the value,
1531             put '~' before number as following.
1532              
1533             key between ~ 4,10
1534              
1535             Note that: use C, instead of 'between ~ #, #'.
1536              
1537             =back
1538              
1539             =head1 HOW TO ADD OPERATOR
1540              
1541             This module has 2 kinds of operator.
1542              
1543             =over 4
1544              
1545             =item normal operator
1546              
1547             This is used in sentence.
1548              
1549             Key Operator Condition
1550             ~~~~~~~~
1551             For example: is, are, match ...
1552              
1553             "v is word" returns structure like a following:
1554              
1555             {
1556             v_is => 1,
1557             v_valid => 1,
1558             }
1559              
1560             =item condition operator
1561              
1562             This is used in sentence only when Operator is 'is/are/isnt/arent'.
1563              
1564             Key Operator Condition
1565             (is/are) ~~~~~~~~~
1566             (isnt/arent)
1567              
1568             This is operator which is used for checking Value(s).
1569             Operator should be 'is' or 'are'(these are same) or 'isnt or arent'(these are same).
1570              
1571             For example: num, alpha, alphanum, word ...
1572              
1573             =back
1574              
1575             You can add these operator with 2 class method.
1576              
1577             =over 4
1578              
1579             =item add_operator
1580              
1581             Data::RuledValidator->add_operator(name => $code);
1582              
1583             $code should return code to make closure.
1584             For example:
1585              
1586             Data::RuledValidaotr->add_operator(
1587             'is' =>
1588             sub {
1589             my($key, $c) = @_;
1590             my $sub = Data::RuledValidaotr->_cond_op($c) || '';
1591             unless($sub){
1592             if($c eq 'n/a'){
1593             return $c;
1594             }else{
1595             Carp::croak("$c is not defined. you can use; " . join ", ", Data::RuledValidaotr->_cond_op);
1596             }
1597             }
1598             return sub {my($self, $v) = @_; $v = shift @$v; return($sub->($self, $v) + 0)};
1599             },
1600             )
1601              
1602             $key and $c is Key and Condition. They are given to $code.
1603             $code receive them and use them as $code likes.
1604             In example, get code ref to use $c(Data::RuledValidaotr->_cond_op($c)).
1605              
1606             return sub {my($self, $v) = @_; $v = shift @$v; return($sub->($self, $v) + 0)};
1607              
1608             This is the code to return closure. To closure, 5 values are given.
1609              
1610             $self, $values, $alias, $obj, $method
1611              
1612             $self = Data::RuledValidaotr object
1613             $values = Value(s). array ref
1614             $alias = alias of Key
1615             $obj = object given in new
1616             $method = method given in new
1617              
1618             In example, first 2 values is used.
1619              
1620             =item add_condition
1621              
1622             Data::RuledValidator->add_condition(name => $code);
1623              
1624             $code should be code ref.
1625             For example:
1626              
1627             __PACKAGE__->add_condition
1628             (
1629             'mail' => sub{my($self, $v) = @_; return Email::Valid->address($v) ? 1 : 0},
1630             );
1631              
1632             =back
1633              
1634             =head1 PLUGIN
1635              
1636             Data::RuledValidator is made with plugins (since version 0.02).
1637              
1638             =head2 How to create plugins
1639              
1640             It's very easy. The name of the modules plugged in this is started from 'Data::RuledValidator::Plugin::'.
1641              
1642             for example:
1643              
1644             package Data::RuledValidator::Plugin::Email;
1645            
1646             use Email::Valid;
1647             use Email::Valid::Loose;
1648            
1649             Data::RuledValidator->add_condition
1650             (
1651             'mail' =>
1652             sub{
1653             my($self, $v) = @_;
1654             return Email::Valid->address($v) ? 1 : ()
1655             },
1656             'mail_loose' =>
1657             sub{
1658             my($self, $v) = @_;
1659             return Email::Valid::Loose->address($v) ? 1 : ()
1660             },
1661             );
1662            
1663             1;
1664              
1665             That's all. If you want to add normal_operator, use add_operator Class method.
1666              
1667             =head1 OVERLOADING
1668              
1669             $valid = $validator_object; # it is as same as $validator_object->valid;
1670             %valid = @$validator_object; # it is as same as %{$validator_object->result};
1671              
1672             =head1 INTERNAL CLASS DATA
1673              
1674             It is just a memo.
1675              
1676             =over 4
1677              
1678             =item %RULE
1679              
1680             All rule for all object(which has different rule file).
1681              
1682             structure:
1683              
1684             rule_name =>
1685             {
1686             _regex_group => [],
1687             # For group name, regexp can be used, for no need to find rule key is regexp or not,
1688             # This exists.
1689             id_key => [],
1690             # Rule has key which identify group name. this hash is {RULE_NAME => key_name}
1691             # why array ref?
1692             # for unique, we can set several key for id_key(it likes SQL unique)
1693             coded_rule => [],
1694             # it is assemble of closure
1695             time => $time
1696             # (stat 'rule_file')[9]
1697             }
1698              
1699             =item %COND_OP
1700              
1701             The keys are condition operator names. The values is coderef(condition operator).
1702              
1703             =item %MK_CLOSURE
1704              
1705             { operator => sub{coderef which create closure} }
1706              
1707             =item %REQUIRED
1708              
1709             { required_key => undef, required_key2 => undef }
1710              
1711             =back
1712              
1713             =head1 NOTE
1714              
1715             Now, once rule is parsed, rule is change to code (assemble of closure) and
1716             it is stored as class data.
1717              
1718             If you use this for CGI, performance is not good.
1719             If you use this on mod_perl, it is good idea.
1720              
1721             I have some solution;
1722              
1723             store code to storable file. store code to shared memory.
1724              
1725             =head1 TODO
1726              
1727             =over 4
1728              
1729             =item can take 2 keys for id_key
1730              
1731             =item More test
1732              
1733             I have to do more test.
1734              
1735             =item More documents
1736              
1737             I have to write more documents.
1738              
1739             =item multiple rule files
1740              
1741             =back
1742              
1743             =head1 AUTHOR
1744              
1745             Ktat, Ektat@cpan.orgE
1746              
1747             =head1 COPYRIGHT
1748              
1749             Copyright 2006-2007 by Ktat
1750              
1751             This program is free software; you can redistribute it
1752             and/or modify it under the same terms as Perl itself.
1753              
1754             See http://www.perl.com/perl/misc/Artistic.html
1755              
1756             =cut