File Coverage

blib/lib/Bio/Polloc/RuleSet/cfg.pm
Criterion Covered Total %
statement 127 162 78.4
branch 42 86 48.8
condition 5 7 71.4
subroutine 19 21 90.4
pod 3 3 100.0
total 196 279 70.2


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Bio::Polloc::RuleSet::cfg - Implementation of Bio::Polloc::RuleIO for .cfg files
4              
5             =head1 DESCRIPTION
6              
7             Reads .cfg files (a.k.a. .bme files) and produces a L<Bio::Polloc::RuleIO>
8             object.
9              
10             =head1 AUTHOR - Luis M. Rodriguez-R
11              
12             Email lmrodriguezr at gmail dot com
13              
14             =head1 IMPLEMENTS OR EXTENDS
15              
16             =over
17              
18             =item *
19              
20             L<Bio::Polloc::RuleIO>
21              
22             =back
23              
24             =cut
25              
26             package Bio::Polloc::RuleSet::cfg;
27 3     3   17 use base qw(Bio::Polloc::RuleIO);
  3         6  
  3         271  
28 3     3   17 use strict;
  3         6  
  3         135  
29 3     3   2418 use Bio::Polloc::Polloc::Config;
  3         10  
  3         127  
30 3     3   791 use Bio::Polloc::RuleI;
  3         9  
  3         78  
31 3     3   1759 use Bio::Polloc::GroupCriteria;
  3         11  
  3         107  
32 3     3   28 use Bio::Polloc::GroupCriteria::operator;
  3         6  
  3         66  
33 3     3   18 use Bio::Seq;
  3         7  
  3         18677  
34             our $VERSION = 1.0503; # [a-version] from Bio::Polloc::Polloc::Version
35              
36              
37             =head1 APPENDIX
38              
39             Methods provided by the package
40              
41             =head2 new
42              
43             Generic initialization method.
44              
45             =head3 Arguments
46              
47             =over
48              
49             =item -init_id I<str>
50              
51             Sets the initial ID (1 by default).
52              
53             =item *
54              
55             Any other parameter accepted by L<Bio::Polloc::RuleIO>.
56              
57             =item *
58              
59             Any other parameter accepted by L<Bio::Polloc::Polloc::Config>.
60              
61             =back
62              
63             =cut
64              
65             sub new {
66 0     0 1 0 my($caller,@args) = @_;
67 0         0 my $self = $caller->SUPER::new(@args);
68 0         0 $self->_initialize(@args);
69 0         0 return $self;
70             }
71              
72             =head2 read
73              
74             Configures and parses the file.
75              
76             =cut
77              
78             sub read {
79 3     3 1 6 my($self,@args) = @_;
80 3         10 $self->_cfg->_register_handle_function(
81             -obj=>$self,
82             -fun=>"_parse_rule",
83             -token=>".rule.add");
84 3         10 $self->_cfg->_register_handle_function(
85             -obj=>$self,
86             -fun=>"_parse_set",
87             -token=>".rule.set");
88 3         9 $self->_cfg->_register_handle_function(
89             -obj=>$self,
90             -fun=>"_parse_set",
91             -token=>".rule.setrule",
92             -defaults=>[-isrule=>1]);
93 3         11 $self->_cfg->_register_handle_function(
94             -obj=>$self,
95             -fun=>"_parse_glob",
96             -token=>".rule.glob");
97 3         10 $self->_cfg->_register_handle_function(
98             -obj=>$self,
99             -fun=>"_parse_glob",
100             -token=>".groupcriteria.glob");
101 3         10 $self->_cfg->_register_handle_function(
102             -obj=>$self,
103             -fun=>"_parse_group_var",
104             -token=>".groupcriteria.var");
105 3         10 $self->_cfg->_register_handle_function(
106             -obj=>$self,
107             -fun=>"_parse_group_eval",
108             -token=>".groupcriteria.eval");
109 3         10 $self->_cfg->_register_handle_function(
110             -obj=>$self,
111             -fun=>"_parse_ext_eval",
112             -token=>".groupextension.eval"
113             );
114 3         10 $self->_cfg->parse(@args);
115             }
116              
117             =head2 value
118              
119             Sets/gets a stored value.
120              
121             =head3 Arguments
122              
123             =over
124              
125             =item -key
126              
127             The key.
128              
129             =item -value
130              
131             The value (if any).
132              
133             =item alert
134              
135             If true, alerts if the key is not set.
136              
137             =back
138              
139             =head3 Returns
140              
141             The value (mix).
142              
143             =cut
144              
145             sub value {
146 0     0 1 0 my($self,@args) = @_;
147 0         0 my($key,$value,$alert) = $self->_rearrange([qw(KEY VALUE ALERT)], @args);
148 0 0       0 $self->_cfg->_save(-key=>$key, -value=>$value, -space=>"rule") if $value;
149              
150             # Search first in the Rule.Set space
151 0         0 $value = $self->_cfg->value(-key=>$key, -space=>"rule.set", -noalert=>1);
152 0 0       0 return $value if defined $value;
153             # Then search in the Rule space
154 0         0 $value = $self->_cfg->value(-key=>$key, -space=>"rule", -noalert=>1);
155 0 0       0 return $value if defined $value;
156             # Search in the root space otherwise
157 0         0 return $self->_cfg->value(-key=>$key, -space=>".", -noalert=>!$alert);
158             }
159              
160             =head1 INTERNAL METHODS
161              
162             Methods intended to be used only within the scope of Bio::Polloc::*
163              
164             =head2 _cfg
165              
166             Sets/gets the L<Bio::Polloc::Polloc::Config> main object.
167              
168             =head3 Throws
169              
170             L<Bio::Polloc::Polloc::Error> if the object is not of the proper class.
171              
172             =cut
173              
174             sub _cfg {
175 69     69   98 my($self,$value) = @_;
176 69 100       129 $self->{'_cfg_obj'} = $value if $value;
177 69 50       140 return unless $self->{'_cfg_obj'};
178 69 50       277 $self->{'_cfg_obj'}->isa('Bio::Polloc::Polloc::Config') or
179             $self->throw("Unexpected type of cfg object", $self->{'_cfg_obj'});
180 69         434 return $self->{'_cfg_obj'};
181             }
182              
183             =head2 _parse_rule
184              
185             Parses the body of an 'add' statement in the Rule namespace.
186              
187             =head3 Throws
188              
189             L<Bio::Polloc::Polloc::Error> if bad format.
190              
191             =cut
192              
193             sub _parse_rule {
194 6     6   14 my($self, $body, $defaults) = @_;
195 6 50       17 $body or $self->throw("Empty body for .rule.add", $body);
196 6 50       47 $body=~m/^\s*(\w+)\s*:\s*([\w\.]+)(\s+at\s+([^']+))?(\s+as\s+'(.+)')?\s*$/i or
197             $self->throw("Bad format for the body of .rule.add, ".
198             "expecting type:name or type:name at context", $body);
199 6         29 my($type,$key,$context,$name) = ($1,$2,$4,$6);
200 6         9 my $value;
201 6 50       15 unless($name) {
202 0         0 $name = $key;
203 0         0 $name =~ s/^\.rule\.//i;
204 0         0 $name =~ s/^\.//;
205             }
206 6         37 my $id = $self->_next_child_id;
207 6 50       35 $value = $self->_cfg->value(-key=>$key, -space=>"rule", -mandatory=>1)
208             unless defined $value;
209 6 50       36 my $rule = Bio::Polloc::RuleI->new(
210             -type=>$type,
211             -format=>$self->format,
212             -name=>$name,
213             -id=>defined $id ? $id : "",
214             -context=>$self->_parse_context($4),
215             -value=>$value);
216 6         54 my $index = $self->add_rule( $rule );
217 6   100     32 $self->{'_key_rule_map'} ||= {};
218 6         24 $self->{'_key_rule_map'}->{ $self->_cfg->_parse_key(-key=>$key, -space=>"rule") } = $index;
219             }
220              
221             =head2 _parse_set
222              
223             Parses the body of the .rule.set and the .rule.setrule statements with the
224             structure [set|setrule] key param='value'. If setrule, the value is replaced
225             by the corresponding Bio::Polloc::RuleI object
226              
227             =head3 Default arguments
228              
229             Arguments passed as an array reference to the second slot:
230              
231             =over
232              
233             =item -isrule I<bool (int)>
234              
235             To distinguish among set (false) and setrule (true)
236              
237             =back
238              
239             =cut
240              
241             sub _parse_set {
242 9     9   18 my($self,$body,$defaults) = @_;
243 9 50       19 $body or $self->throw("Empty body for .rule.set", $body);
244 9 50       45 $body =~ m/^\s*([^\s]+)\s+([\w-]+)\s*=\s*'(.*)'\s*/i or
245             $self->throw("Bad format for the body of .rule.set, ".
246             "expecting key param='value'", $body);
247 9         26 my($key,$param,$value) = ($1,$2,$3);
248 9         17 my($isrule) = $self->_rearrange([qw(ISRULE)], @{$defaults});
  9         33  
249 9         32 my $index = $self->{'_key_rule_map'}->{ $self->_cfg->_parse_key(-key=>$key, -space=>"rule") };
250 9         51 $self->debug("Setting $param as $value on $key ($index)");
251 9 100       22 if($isrule){
252 6         18 my $obj = $self->{'_key_rule_map'}->{ $self->_cfg->_parse_key(-key=>$value, -space=>"rule") };
253 6         27 $self->debug("Map $value: $obj");
254 6 50       15 $self->throw("Impossible to locate the rule $value",$obj) unless defined $obj;
255 6         35 $self->get_rule($index)->safe_value($param, $self->get_rule($obj));
256             }else{
257 3         11 $self->get_rule($index)->safe_value($param, $value);
258             }
259             }
260              
261             =head2 _parse_glob
262              
263             =cut
264              
265             sub _parse_glob {
266 9     9   15 my($self,$body,$defaults) = @_;
267 9 50       23 $body or $self->throw("Empty body for .rule.glob", $body);
268 9 50       56 $body =~ m/^\s*(\w+)\s*=\s*'(.*)'\s*/i or
269             $self->throw("Bad format for the body of .rule.glob, ".
270             "expecting param='value'", $body);
271 9         31 my($param,$value) = (lc($1), $2);
272 9         58 $self->safe_value($param, $value);
273             }
274              
275             =head2 _parse_group_var
276              
277             =cut
278              
279             sub _parse_group_var {
280 48     48   66 my($self,$body,$defaults) = @_;
281 48 50       92 $body or $self->throw("Empty body for .groupcriteria.var", $body);
282 48 50       224 $body =~ m/^([^\s]+)\s+([^\s=]+)\s*=\s*(.*)\s*/i or
283             $self->throw("Bad format for the body of .rule.glob, ".
284             "expecting type name = operation...", $body);
285 48         232 my %groupcriteria = (-type=>lc($1), -operation=>$3);
286 48 100       110 $self->{'_groupcriteria'} = {} unless defined $self->{'_groupcriteria'};
287 48         200 $self->debug("Saving '$2'");
288 48         256 $self->{'_groupcriteria'}->{$2} = Bio::Polloc::GroupCriteria::operator->new(%groupcriteria);
289             }
290              
291             =head2 _parse_group_eval
292              
293             =cut
294              
295             sub _parse_group_eval {
296 3     3   7 my($self, $body,$defaults) = @_;
297 3 50       15 return unless defined $self->{'_groupcriteria'};
298 3 50       17 defined $self->{'_groupcriteria'}->{$body} or
299             $self->throw("Impossible to evaluate an undefined variable", $body);
300 3         22 my $group = new Bio::Polloc::GroupCriteria(
301             -source=>$self->safe_value("source"),
302             -target=>$self->safe_value("target"));
303 3         18 $group->condition($self->_parse_group_operation($body, $defaults));
304             # $self->vardump($group->condition);
305 3         56 $self->addgrouprules($group);
306             }
307              
308             =head2 _parse_ext_eval
309              
310             =cut
311              
312             sub _parse_ext_eval {
313 3     3   6 my($self, $body, $defaults) = @_;
314 3 50       21 defined $self->{'_groupcriteria'}
315             or $self->throw("Defining group extension but no grouping rule defined", $body);
316 3         7 my @groups = @{$self->grouprules};
  3         35  
317 3         20 my $group = $groups[$#groups];
318 3         15 $group->extension($self->_cfg->value(-key=>$body, -space=>"groupextension", -mandatory=>1));
319             }
320              
321             =head2 _parse_group_operation
322              
323             =cut
324              
325             sub _parse_group_operation {
326 93     93   146 my($self,$name,$defaults) = @_;
327 93 100 66     504 return Bio::Polloc::GroupCriteria::operator->new(-type=>'cons', -operation=>$name, -name=>$name) if defined $name and $name =~ /^FEAT[12]$/;
328 69         137 my $body = $self->{'_groupcriteria'}->{$name};
329 69 50       127 defined $body or $self->throw("Impossible to locate the variable $name", $body);
330 69         191 my $t = $body->type;
331 69         210 my $o = $body->operation;
332 69 50       148 defined $t or $self->throw("You declared an operation without return type", $body);
333 69 50       137 defined $o or $self->throw("You declared an operation without body", $body);
334 69         221 $o =~ s/^\s*//;
335 69         364 $o =~ s/\s*$//;
336 69 100       210 if($t eq 'bool'){
    100          
    50          
337 21 50       176 if($o =~ m/^(t(rue)?|1)$/i){
    50          
    50          
    0          
338 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'bool', -val=>1, -name=>$name);
339             }elsif($o =~ m/^(f(alse)?|0)$/i){
340 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'bool', -val=>0, -name=>$name);
341             }elsif($o =~ m/^([^\s]+)\s*([><]=?|&&?|\|\|?|\^|and|or|xor)\s*([^\s]+)$/i){
342 21         66 my($o1b,$f,$o2b) = ($1,$2,$3);
343 21         132 my $o1 = $self->_parse_group_operation($o1b, $defaults);
344 21         51 my $o2 = $self->_parse_group_operation($o2b, $defaults);
345 21         134 return Bio::Polloc::GroupCriteria::operator->new(-type=>'bool', -operators=>[$o1, $o2], -operation=>$f, -name=>$name);
346             }elsif($o =~ m/^(!|not)\s*([^\s]+)$/i){
347 0         0 my $f = $1;
348 0         0 my $o1 = $self->_parse_group_operation($2, $defaults);
349 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'bool', -operators=>[$o1], -operation=>$f, -name=>$name);
350             }else{
351 0         0 $self->throw("Impossible to parse boolean", $body);
352             }
353             }elsif($t eq 'num'){
354 24 100       158 if($o =~ m/^[-+]?\d*\.?\d+(e[-+]?\d*\.?\d+)?$/) {
    50          
355 12         79 return Bio::Polloc::GroupCriteria::operator->new(-type=>'num', -val=>$o+0, -name=>$name);
356             }elsif($o =~ m/^([^\s]*)\s*(\+|\-|\*\*?|\/|\^|%|aln-sim( with)?|aln-score( with)?)\s*([^\s]*)$/i){
357 12         34 my($o1b,$f,$o2b) = ($1,$2,$5);
358 12         59 my $o1 = $self->_parse_group_operation($o1b, $defaults);
359 12         30 my $o2 = $self->_parse_group_operation($o2b, $defaults);
360 12         83 return Bio::Polloc::GroupCriteria::operator->new(-type=>'num', -operators=>[$o1, $o2], -operation=>$f, -name=>$name);
361             }else{
362 0         0 $self->throw("Impossible to parse number", $body);
363             }
364             }elsif($t eq 'seq'){
365 24 50       183 if($o =~ m/^[A-Za-z]+$/){
    50          
    0          
    0          
366 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'seq', -val=>Bio::Seq->new(-seq=>$o), -name=>$name);
367             }elsif($o =~ m/^([^\s]+)\s+(at)\s*\[(-?\d)\s*[,;]\s*(-?\d+)\s*\.\.\s*(-?\d+)\]$/i){
368 24         104 my($o1b,$extra1,$extra2,$extra3) = ($1, $3+0, $4+0, $5+0);
369 24         101 my $o1 = $self->_parse_group_operation($o1b, $defaults);
370 24         147 return Bio::Polloc::GroupCriteria::operator->new(
371             -type=>'seq', -operators=>[$o1, $extra1, $extra2, $extra3],
372             -operation=>'sequence', -name=>$name);
373             }elsif($o =~ m/^rev(comp?( of)?)?\s+([^\s]+)$/i){
374 0         0 my $o1 = $self->_parse_group_operation($3, $defaults);
375 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'seq', -operators=>[$o1], -operation=>'reverse', -name=>$name);
376             }elsif($o =~ m/^seq\s+([^\s]+)/){
377 0         0 my $o1 = $self->_parse_group_operation($1, $defaults);
378 0         0 return Bio::Polloc::GroupCriteria::operator->new(-type=>'seq', -operators=>[$o1], -operation=>'sequence', -name=>$name);
379             }else{
380 0         0 $self->throw("Impossible to parse number", $body);
381             }
382             }
383             }
384              
385             =head2 _parse_context
386              
387             =cut
388              
389             sub _parse_context {
390 6     6   15 my($self,@args) = @_;
391 6         24 my($context) = $self->_rearrange([qw(CONTEXT)], @args);
392 6   50     58 $context ||= "default";
393 6         25 $self->debug("Parsing context '$context'");
394 6 50       69 return [0,0,0] if $context eq "default";
395 0         0 $context =~ s/^[\[\(]+//;
396 0         0 $context =~ s/[\]\)]+$//;
397 0 0       0 if($context=~m/^([+-]?\d)\s*([;,:-]|\.\.)\s*([+-]?\d+)\s*([;,:-]|\.\.)\s*([+-]?\d+)/){
398 0         0 return [$1+0, $3+0, $5+0];
399             }
400 0 0       0 if($context=~m/^[+-]?0+([;,-]|\.\.|)$/){
401 0         0 return [0,0,0];
402             }
403 0         0 return [0,0,0];
404             }
405              
406             =head2 _parse_cfg
407              
408             =cut
409              
410             sub _parse_cfg {
411 3     3   7 my($self,@args) = @_;
412 3         34 $self->_cfg( Bio::Polloc::Polloc::Config->new(-noparse=>1, @args) );
413 3         13 $self->_cfg->spaces(".rule");
414 3         8 $self->_cfg->spaces(".groupcriteria");
415 3         11 $self->_cfg->spaces(".groupextension");
416 3         12 $self->read(@args);
417             }
418              
419             =head2 _initialize
420              
421             =cut
422              
423             sub _initialize {
424 3     3   9 my($self,@args) = @_;
425 3         14 my($init_id) = $self->_rearrange([qw(INIT_ID)], @args);
426 3         24 $self->init_id($init_id);
427 3         10 $self->_parse_cfg(@args);
428             }
429              
430              
431             1;