File Coverage

blib/lib/Mail/Lite/Processor.pm
Criterion Covered Total %
statement 97 112 86.6
branch 30 46 65.2
condition 9 12 75.0
subroutine 15 15 100.0
pod 2 2 100.0
total 153 187 81.8


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # FILE: Processor.pm
4             #
5             # DESCRIPTION: Processor -- processor based on rules chain
6             #
7             # FILES: ---
8             # BUGS: ---
9             # NOTES: ---
10             # AUTHOR: Pavel Boldin (),
11             # COMPANY:
12             # VERSION: 1.0
13             # CREATED: 14.09.2008 14:27:25 MSD
14             # REVISION: ---
15             #===============================================================================
16              
17             package Mail::Lite::Processor;
18              
19 2     2   110646 use strict;
  2         6  
  2         237  
20 2     2   16 use warnings;
  2         4  
  2         76  
21              
22 2     2   1839 use UNIVERSAL::require;
  2         3978  
  2         20  
23 2     2   1255 use Mail::Lite::Constants;
  2         7  
  2         143  
24              
25 2     2   1656 use Clone qw/clone/;
  2         8180  
  2         166  
26              
27 2     2   2238 use Smart::Comments -ENV;
  2         86105  
  2         17  
28              
29 2     2   4970 use Mail::Lite::Message;
  2         8  
  2         40  
30              
31              
32             my $_processors_cache;
33              
34             sub new {
35 147     147 1 278 my $self = shift;
36              
37 147         525 $self = bless {}, $self;
38 147         707 $self->_init( @_ );
39              
40 147         460 return $self;
41             }
42              
43             sub _init {
44 147     147   223 my $self = shift;
45 147         384 my %param = @_;
46              
47 147   100     874 $self->{rules} = $param{rules} || [];
48 147         884 $self->{handler} = $param{handler};
49 147         385 $self->{debug} = $param{debug};
50              
51 147 100       302 if ( @{ $self->{rules} } ) {
  147         536  
52 2438         6074 my @common_rules = grep { $_->{id} =~ m/^_common\./ }
  75         208  
53 75         127 @{ $self->{rules} };
54              
55             # for debuggin -- if there some missing common rules
56 75         265 my %common_rules = map { $_->{id} => $_ } @common_rules;
  0         0  
57 75         179 $self->{common_rules} = \%common_rules;
58 75         257 $self->_replace_common_rules;
59             }
60              
61             #use Data::Dumper;
62             #die Dumper $self->{rules};
63             }
64              
65             sub _replace_common_rules {
66 75     75   131 my $self = shift;
67              
68 75         155 my $common_rules = $self->{common_rules };
69 75         176 my $rules = $self->{rules };
70              
71 75         180 foreach my $rule (@$rules) {
72 2438 100       6796 if ( not exists $rule->{match} ) {
73 4         7 next;
74             }
75              
76             $self->_replace_common_rules_in_hash(
77 2434         7101 \$rule->{match},
78             );
79             }
80             }
81              
82             sub _replace_common_rules_in_hash {
83 17311     17311   23041 my $self = shift;
84 17311         18282 my $ref = shift;
85              
86 17311 100       39909 if ( ref $ref eq 'REF' ) {
87 10273         13915 $ref = $$ref;
88             }
89              
90 17311 100       53454 if ( ref $ref eq 'ARRAY' ) {
    100          
    50          
91 3235         10348 $self->_replace_common_rules_in_hash( \$_ ) foreach @$ref;
92             }
93             elsif ( ref $ref eq 'HASH' ) {
94 7038         24776 $self->_replace_common_rules_in_hash( \$_ ) foreach values %$ref;
95             }
96             elsif ( ref $ref eq 'SCALAR' ) {
97 7038 50 66     7034 if ( ${ $ref } && ${ $ref } =~ m/^_common\./ ) {
  7038         33644  
  6328         47370  
98 0         0 my $common_rule_name = ${ $ref };
  0         0  
99              
100 0 0       0 if ( ! exists $self->{common_rules}{ $common_rule_name } ) {
101 0         0 die "Cannot find common rule $common_rule_name";
102             }
103              
104 0         0 ${ $ref } = $self->{common_rules}{ $common_rule_name }->{ match };
  0         0  
105 0 0       0 ${ $ref }
  0         0  
106             or die "Cannot find match hash in $common_rule_name";
107             }
108             }
109             else {
110 0         0 die "Unknown reference type given ", ref $ref;
111             }
112             }
113              
114              
115             # Process message
116             # INS: $self, %param
117             # %param: message, handler, rules
118             sub process {
119 308     308 1 2329 my ($self, %param) = @_;
120              
121 308 100       2657 if ( not ref $self ) {
122 75         431 $self = $self->new( %param );
123             }
124            
125 308 50       1492 my $message = ((ref $param{message}) =~ /::/)
126             ? $param{message} # Ýòî óæå îáúåêò
127             : Mail::Lite::Message->new( $param{message} ); # Åù¸ íå îáúåêò
128              
129             # Ok, make that probaby, we should use some caching there
130 308         1107 $self->_process_by_rule_chain( $message, $param{handler} );
131             }
132              
133             # Check if message match some rule
134             # IN: message (Mail::Lite::Message object), handler, recursive
135             sub _process_by_rule_chain {
136 308     308   696 my ($self, $message, $handler, $recursive) = @_;
137              
138 308   33     1086 $handler ||= $self->{handler};
139              
140 308         399 my @rules = grep { not $_->{id} =~ /^_/; } @{ $self->{rules} };
  3081         9307  
  308         758  
141              
142 3197   100     13487 @rules = sort {
      100        
143 308         1385 ($a->{weight} || 0) <=> ($b->{weight} || 0)
144             } @rules;
145              
146             RULE:
147 308         676 foreach my $rule ( @rules ) {
148             ### $rule
149 680         1197 my $processors = $rule->{processors};
150              
151 680 50       1494 unless ( $processors ) {
152 0         0 $processors = [
153             {
154             processor => 'Stub',
155             }
156             ]
157             #die "no processors given for $rule->{id}";
158             }
159              
160 680         2960 my $match_processor = {
161             processor => 'match',
162             match_rules => $rule->{match}
163             };
164              
165 680         3179 my $input = $message;
166 680         726 my $output;
167              
168             PROCESSOR:
169 680         1211 foreach my $processor ($match_processor, @$processors) {
170              
171 1261 100       2515 $input = defined $output ? $output : $input;
172              
173 1261         3598 my $processor_sub =
174             _get_processor_method( $processor->{processor} );
175              
176 1261         11536 my $result = $processor_sub->(
177             {
178             processor => $processor ,
179             input => $input ,
180             output => \$output ,
181             rule => $rule ,
182             rules => $self->{rules},
183             }
184             );
185              
186 1261 100       5316 if ( OK eq $result ) {
    50          
    100          
    50          
    0          
187 771         2520 next PROCESSOR;
188             }
189             elsif ( STOP eq $result ) {
190 0         0 last PROCESSOR;
191             }
192             elsif ( NEXT_RULE eq $result ) {
193 373         1977 next RULE;
194             }
195             elsif ( STOP_RULE eq $result ) {
196 117         579 $handler->( $rule->{id}, $output );
197 117         3214 last RULE;
198             }
199             elsif ( ERROR eq $result ) {
200 0         0 die "ERROR in $rule->{id}'s $processor->{processor}";
201             }
202              
203             }
204              
205             # ok, call handler
206 190         1705 $handler->( $rule->{id}, $output );
207             }
208             }
209              
210              
211             sub _get_processor_method {
212 1261     1261   2548 my $processor = shift;
213              
214 1261 50       2806 return $processor if ref $processor eq 'CODE';
215              
216 1261 100       3254 if ( exists $_processors_cache->{ $processor } ) {
217 1249         3308 return $_processors_cache->{ $processor };
218             }
219              
220 12 50       84 unless ( $processor =~ s/^\+// ) {
221 2     2   3284 no strict 'refs';
  2         12  
  2         352  
222              
223 12         61 my $pkgname = join '', map { ucfirst $_ } split /[_ ]/, $processor;
  15         64  
224              
225 12         32 $pkgname = 'Mail::Lite::Processor::'.$pkgname;
226              
227 12 50       105 if ( not $pkgname->require ) {
228 0         0 die "cannot find processors $processor: $@";
229             }
230            
231 12 50       327 my $c = $pkgname->can('process')
232             or die "cannot use processor $processor";
233              
234 12         68 return $_processors_cache->{ $processor } = $c;
235             }
236              
237 0           die "not yet implemented";
238             }
239              
240             1;