File Coverage

blib/lib/Bio/Polloc/RuleI.pm
Criterion Covered Total %
statement 115 151 76.1
branch 52 94 55.3
condition 7 21 33.3
subroutine 17 25 68.0
pod 14 14 100.0
total 205 305 67.2


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Bio::Polloc::RuleI - Generic rules interface
4              
5             =head1 DESCRIPTION
6              
7             Use this interface to initialize the Bio::Polloc::Rule::* objects. Any
8             rule inherits from this Interface. Usually, rules are initialized
9             in sets (via the L<Bio::Polloc::RuleIO> package).
10              
11             =head1 AUTHOR - Luis M. Rodriguez-R
12              
13             Email lmrodriguezr at gmail dot com
14              
15             =head1 IMPLEMENTS OR EXTENDS
16              
17             =over
18              
19             =item *
20              
21             L<Bio::Polloc::Polloc::Root>
22              
23             =back
24              
25             =cut
26              
27             package Bio::Polloc::RuleI;
28 10     10   722 use strict;
  10         19  
  10         350  
29 10     10   48 use base qw(Bio::Polloc::Polloc::Root);
  10         18  
  10         3714  
30 10     10   5680 use Bio::Polloc::RuleIO;
  10         24  
  10         20288  
31             our $VERSION = 1.0503; # [a-version] from Bio::Polloc::Polloc::Version
32              
33              
34             =head1 APPENDIX
35              
36             Methods provided by the package
37              
38             =cut
39              
40             =head2 new
41              
42             =over
43              
44             =item
45              
46             Attempts to initialize a C<Bio::Polloc::Rule::*> object
47              
48             =item Arguments
49              
50             =over
51              
52             =item -type
53              
54             The type of rule
55              
56             =item -value
57              
58             The value of the rule (depends on the type of rule)
59              
60             =item -context
61              
62             The context of the rule. See L<Bio::Polloc::RuleI-E<gt>context>.
63              
64             =back
65              
66             =item Returns
67              
68             The C<Bio::Polloc::Rule::*> object
69              
70             =item Throws
71              
72             L<Bio::Polloc::Polloc::Error> if unable to initialize the proper object
73              
74             =back
75              
76             =cut
77              
78             sub new {
79 6     6 1 29 my($caller,@args) = @_;
80 6   33     32 my $class = ref($caller) || $caller;
81            
82             # Pre-fix based on type, unless the caller is a proper class
83 6 50       18 if($class !~ m/Bio::Polloc::Rule::(\S+)/){
84 6         41 my $bme = Bio::Polloc::Polloc::Root->new(@args);
85 6         29 my($type) = $bme->_rearrange([qw(TYPE)], @args);
86            
87 6 50       20 if($type){
88 6         24 $type = Bio::Polloc::RuleI->_qualify_type($type);
89 6 50       35 $class = "Bio::Polloc::Rule::" . $type if $type;
90             }
91             }
92              
93             # Try to load the object
94 6 50       33 if($class =~ m/Bio::Polloc::Rule::(\S+)/){
95 6 50       34 if(Bio::Polloc::RuleI->_load_module($class)){;
96 6         57 my $self = $class->SUPER::new(@args);
97 6         70 $self->debug("Got the RuleI class $class ($1)");
98 6         59 my($value,$context,$name,$id,$executable) =
99             $self->_rearrange([qw(VALUE CONTEXT NAME ID EXECUTABLE)], @args);
100 6         53 $self->value($value);
101 6         10 $self->context(@{$context});
  6         41  
102 6         36 $self->name($name);
103 6         34 $self->id($id);
104 6         35 $self->executable($executable);
105 6         19 $self->_initialize(@args);
106 6         30 return $self;
107             }
108 0         0 my $bme = Bio::Polloc::Polloc::Root->new(@args);
109 0         0 $bme->throw("Impossible to load the module", $class);
110             }
111              
112             # Throws exception if any previous return
113 0         0 my $bme = Bio::Polloc::Polloc::Root->new(@args);
114 0         0 $bme->throw("Impossible to load the proper Bio::Polloc::RuleI class with ".
115             "[".join("; ",@args)."]", $class);
116             }
117              
118             =head2 type
119              
120             =over
121              
122             =item
123              
124             Gets/sets the type of rule
125              
126             =item Arguments
127              
128             Value (str). Can be: pattern, profile, repeat, tandemrepeat, similarity, coding,
129             boolean, composition, crispr. See the corresponding C<Bio::Polloc::Rule::*> objects
130             for further details.
131              
132             Some variations can be introduced, like case variations or short versions like
133             B<patt> or B<rep>.
134              
135             =item Return
136              
137             Value (str). The type of the rule, or C<undef> if undefined. The value returned
138             is undef or a string from the above list, regardless of the input variations.
139              
140             =item Throws
141              
142             L<Bio::Polloc::Polloc::Error> if an unsupported type is received.
143              
144             =back
145              
146             =cut
147              
148             sub type {
149 9     9 1 23 my($self,$value) = @_;
150 9 100       23 if($value){
151 6         54 my $v = $self->_qualify_type($value);
152 6 50       18 $self->throw("Attempting to set an invalid type of rule",$value) unless $v;
153 6         19 $self->{'_type'} = $v;
154             }
155 9         37 return $self->{'_type'};
156             }
157              
158              
159              
160             =head2 context
161              
162             =over
163              
164             =item
165              
166             Gets/sets the context of the rule.
167              
168             The context is a reference to an array of two elements (I<int> or I<str>),
169             the first being:
170             1 => with respect to the start of the sequence
171             0 => somewhere within the sequence (ignores the second)
172             -1 => with respect to the end of the sequence
173              
174             And the second being the number of residues from the reference point. The second
175             value can be positive, negative, or zero.
176              
177             =item Arguments
178              
179             Three integers, or one integer equal to zero. Please note that this function is
180             extremely tolerant, and tries to guess the context regardless of the input.
181              
182             =item Returns
183              
184             A reference to the array described above.
185              
186             =back
187              
188             =cut
189              
190             sub context {
191 11     11 1 26 my($self,@args) = @_;
192 11 100       33 if($#args>=0){
193 6         29 $self->{'_context'} = [$args[0]+0, $args[1]+0, $args[2]+0];
194             }
195 11   50     36 $self->{'_context'} ||= [0,0,0];
196 11 50       47 if($self->{'_context'}->[0] < 0) {$self->{'_context'}->[0] = -1;}
  0 50       0  
  0         0  
197 11         18 elsif($self->{'_context'}->[0] > 0) {$self->{'_context'}->[0] = 1;}
198             else {$self->{'_context'}->[0] = 0;}
199 11         20 $self->{'_context'}->[1]+=0;
200 11         44 return $self->{'_context'};
201             }
202              
203             =head2 value
204              
205             =over
206              
207             =item
208              
209             Gets/sets the value of the rule
210              
211             =item Arguments
212              
213             Value (mix)
214              
215             =item Returns
216              
217             Value (mix)
218              
219             =item Note
220              
221             This function relies on C<_qualify_value>
222              
223             =item Throws
224              
225             L<Bio::Polloc::Polloc:Error> if unsupported value is received
226              
227             =back
228              
229             =cut
230              
231             sub value {
232 65     65 1 75 my($self,$value) = @_;
233 65 100       117 if(defined $value){
234 6         31 my $v = $self->_qualify_value($value);
235 6 50       20 defined $v or $self->throw("Bad rule value", $value);
236 6         16 $self->{'_value'} = $v;
237             }
238 65         222 return $self->{'_value'};
239             }
240              
241             =head2 executable
242              
243             =over
244              
245             =item
246              
247             Sets/gets the C<executable> property. A rule can be executed even if this
248             property is false, if the L<Bio::Polloc::RuleI::execute> method is called directly
249             (C<$rule-E<gt>execute>) or by other rule. This property is provided only for
250             L<Bio::Polloc::RuleIO> objects.
251              
252             =item Arguments
253              
254             Boolean (0 or 1; optional)
255              
256             =item Returns
257              
258             1 if expicilty executable, 0 otherwise
259              
260             =item Note
261              
262             It is advisable to have only few (ideally one) executable rules, handling
263             all the others with the rule type B<operation>
264              
265             =back
266              
267             =cut
268              
269             sub executable {
270 7     7 1 22 my($self,$value) = @_;
271 7 50       21 $self->{'_executable'} = $value+0 if defined $value;
272 7 50       54 $self->{'_executable'} = $self->safe_value('executable')
273             unless defined $self->{'_executable'};
274 7 50 66     39 $self->{'_executable'} =
    100          
275             (defined $self->{'_executable'} && $self->{'_executable'} =~ m/^(t|1|y)/i) ? 1 :
276             (defined $self->{'_executable'} ? 0 : undef);
277 7         17 return $self->{'_executable'};
278             }
279              
280              
281             =head2 name
282              
283             =over
284              
285             =item
286              
287             Sets/gets the name of the rule
288              
289             =item Arguments
290              
291             Name (str), the name to set
292              
293             =item Returns
294              
295             The name (str or undef)
296              
297             =back
298              
299             =cut
300              
301             sub name {
302 9     9 1 18 my($self,$value) = @_;
303 9 100       32 $self->{'_name'} = $value if defined $value;
304 9         23 return $self->{'_name'};
305             }
306              
307              
308             =head2 id
309              
310             =over
311              
312             =item
313              
314             Sets/gets the ID of the rule
315              
316             =item Purpose
317              
318             Provide a somewhat I<unique> but human-readable identifier
319              
320             =item Arguments
321              
322             The supposedly unique ID of the rule (str), any dot (B<.>) will be changed to B<_>
323              
324             =item Returns
325              
326             The ID (str or undef)
327              
328             =back
329              
330             =cut
331              
332             sub id {
333 7     7 1 16 my($self,$value) = @_;
334 7 100       24 if($value){
335 6         13 $value =~ s/\./_/g;
336 6         31 $self->debug("Setting Locus ID '$value'");
337 6         15 $self->{'_id'} = $value;
338             }
339 7         15 return $self->{'_id'};
340             }
341              
342             =head2 restart_index
343              
344             =cut
345              
346             sub restart_index {
347 0     0 1 0 my $self = shift;
348 0         0 $self->{'_children_id'} = 1;
349             }
350              
351             =head2 stringify
352              
353             =over
354              
355             =item
356              
357             Provides an easy method for the (I<str>) description of any L<Bio::Polloc::RuleI> object.
358              
359             =item Returns
360              
361             The stringified object (str, off course)
362              
363             =back
364              
365             =cut
366              
367             sub stringify {
368 1     1 1 2 my($self,@args) = @_;
369 1         3 my $out = ucfirst $self->type;
370 1 50       4 $out.= " '" . $self->name . "'" if defined $self->name;
371 1 50       28 $out.= " at [". join("..", @{$self->context}) . "]" if $self->context->[0];
  0         0  
372 1 50       4 $out.= ": ".$self->stringify_value if defined $self->value;
373 1         6 return $out;
374             }
375              
376             =head2 stringify_value
377              
378             =over
379              
380             =item
381              
382             Dummy function to be overriten if non-string value like in Bio::Polloc::Rule::repeat
383              
384             =item Returns
385              
386             The value as string
387              
388             =back
389              
390             =cut
391              
392             sub stringify_value {
393 0     0 1 0 my($self,@args) = @_;
394 0         0 return "".$self->value(@args);
395             }
396              
397             =head2 ruleset
398              
399             =over
400              
401             =item
402              
403             Gets/sets the parent ruleset of the rule
404              
405             =item Arguments
406              
407             The ruleset to set (a L<Bio::Polloc::RuleIO> object).
408              
409             =item Returns
410              
411             A L<Bio::Polloc::RuleIO> object or C<undef>.
412              
413             =back
414              
415             =cut
416              
417             sub ruleset {
418 7     7 1 13 my($self,$value) = @_;
419 7 100       21 if(defined $value){
420 6 50       46 $self->throw("Unexpected type of value '".ref($value)."'",$value)
421             unless $value->isa('Bio::Polloc::RuleIO');
422 6         13 $self->{'_ruleset'} = $value;
423             }
424 7         359 return $self->{'_ruleset'};
425             }
426              
427             =head2 execute
428              
429             =over
430              
431             =item
432              
433             Evaluates the rule in a given sequence.
434              
435             =item Arguments
436              
437             A L<Bio::Seq> object.
438              
439             =item Returns
440              
441             An array of Bio::Polloc::LocusI objects
442              
443             =item Throws
444              
445             A L<Bio::Polloc::Polloc::NotImplementedException> if not implemented
446              
447             =back
448              
449             =cut
450              
451 0     0 1 0 sub execute { $_[0]->throw("execute", $_[0], "Bio::Polloc::Polloc::NotImplementedException") }
452              
453             =head2 safe_value
454              
455             =over
456              
457             =item
458              
459             Sets/gets a parameter of arbitrary name and value
460              
461             =item Purpose
462              
463             To provide a safe interface for setting values from the parsed file
464              
465             =item Arguments
466              
467             =over
468              
469             =item -param
470              
471             The parameter's name (case insensitive)
472              
473             =item -value
474              
475             The value of the parameter (optional)
476              
477             =back
478              
479             =item Returns
480              
481             The value of the parameter or undef
482              
483             =back
484              
485             =cut
486              
487             sub safe_value {
488 16     16 1 31 my ($self,@args) = @_;
489 16         56 my($param,$value) = $self->_rearrange([qw(PARAM VALUE)], @args);
490 16   100     97 $self->{'_safe_values'} ||= {};
491 16 50       29 return unless $param;
492 16         25 $param = lc $param;
493 16 100       43 if(defined $value){
494 9         21 $self->{'_safe_values'}->{$param} = $value;
495             }
496 16         56 return $self->{'_safe_values'}->{$param};
497             }
498              
499              
500             =head2 source
501              
502             =over
503              
504             =item
505              
506             Sets/gets the source of the annotation
507              
508             =item Arguments
509              
510             The source (I<str>)
511              
512             =item Returns
513              
514             The source (I<str> or C<undef>)
515              
516             =back
517              
518             =cut
519              
520             sub source {
521 1     1 1 3 my($self,$source) = @_;
522 1 50       166 $self->{'_source'} = $source if defined $source;
523 1   33     9 $self->{'_source'} ||= $self->type;
524 1         4 return $self->{'_source'};
525             }
526              
527             =head1 INTERNAL METHODS
528              
529             Methods intended to be used only witin the scope of Bio::Polloc::*
530              
531             =head2 _qualify_type
532              
533             =cut
534              
535             sub _qualify_type {
536 12     12   24 my($self,$value) = @_;
537 12 50       28 return unless $value;
538 12         18 $value = lc $value;
539 12 50       60 $value = "pattern" if $value=~/^(patt(ern)?)$/;
540 12 50       27 $value = "profile" if $value=~/^(prof(ile)?)$/;
541 12 50       30 $value = "repeat" if $value=~/^(rep(eat)?)$/;
542 12 100       63 $value = "tandemrepeat" if $value=~/^(t(andem)?rep(eat)?)$/;
543 12 50       52 $value = "similarity" if $value=~/^((sequence)?sim(ilarity)?|homology|ident(ity)?)$/;
544 12 50       26 $value = "coding" if $value=~/^(cod|cds)$/;
545 12 100       47 $value = "boolean" if $value=~/^(oper(at(e|or|ion))?|bool(ean)?)$/;
546 12 50       33 $value = "composition" if $value=~/^(comp(osition)?|content)$/;
547 12         23 return $value;
548             # TRUST IT! -lrr if $value =~ /^(pattern|profile|repeat|tandemrepeat|similarity|coding|boolean|composition|crispr)$/;
549             }
550              
551             =head2 _parameters
552              
553             =over
554              
555             =item
556              
557             Returns the supported parameters for L<value>.
558              
559             =item Returns
560              
561             The supported value keys (C<arrayref>).
562              
563             =back
564              
565             =cut
566              
567 0     0   0 sub _parameters { $_[0]->throw('_parameters', $_[0], 'Bio::Polloc::Polloc::NotImplementedException') }
568              
569             =head2 _qualify_value
570              
571             =over
572              
573             =item
574              
575             Takes the different possible values and returns them the way they must be
576             saved (usually a I<hashref>). Bio::Polloc::Rule::* modules must reimplement
577             either L<_qualify_value> or L<_parameters>.
578              
579             =back
580              
581             =cut
582              
583 3     3   25 sub _qualify_value { return shift->_qualify_value_default(@_) }
584              
585             =head2 _qualify_value_default
586              
587             =cut
588              
589             sub _qualify_value_default {
590 3     3   8 my($self,$value) = @_;
591 3 50       13 unless (defined $value){
592 0         0 $self->warn("Empty value");
593 0         0 return;
594             }
595 3 50       13 if(ref($value) =~ m/hash/i){
596 0         0 my @arr = %{$value};
  0         0  
597 0         0 $value = \@arr;
598             }
599 3 50       49 my @args = ref($value) =~ /array/i ? @{$value} : split /\s+/, $value;
  0         0  
600            
601 3 50       44 return unless defined $args[0];
602 3 50       21 if($args[0] !~ /^-/){
603 0         0 $self->warn("Expecting parameters in the format -parameter value", @args);
604 0         0 return;
605             }
606 3 50       14 unless($#args%2){
607 0         0 $self->warn("Unexpected (odd) number of parameters", @args);
608 0         0 return;
609             }
610 3         44 my %vals = @args;
611 3         7 my $out = {};
612 3         7 for my $k ( @{$self->_parameters} ){
  3         17  
613 42         141 my $p = $self->_rearrange([$k], @args);
614 42 50       100 next unless defined $p;
615             # This checks numeric values, but it's too restrictive
616             #if( $p !~ /^[\d\.eE+-]+$/ ){
617             # $self->warn("Unexpected value for ".$k, $p);
618             # return;
619             #}
620 42         108 $out->{"-".lc $k} = $p;
621             }
622 3         25 return $out;
623             }
624              
625             =head2 _executable
626              
627             =over
628              
629             =item
630              
631             Attempts to find the executable
632              
633             =item Arguments
634              
635             =over
636              
637             =item *
638              
639             An alternative path to search at I<str>.
640              
641             =back
642              
643             =back
644              
645             =cut
646              
647 0     0     sub _executable { $_[0]->throw("_executable", $_[0], "Bio::Polloc::Polloc::NotImplementedException") }
648              
649             =head2 _initialize
650              
651             =cut
652              
653 0     0     sub _initialize { $_[0]->throw("_initialize", $_[0], "Bio::Polloc::Polloc::NotImplementedException") }
654              
655             =head2 _search_value
656              
657             =over
658              
659             =item Arguments
660              
661             The key (I<str>)
662              
663             =item Returns
664              
665             The value (mix) or undef
666              
667             =back
668              
669             =cut
670              
671             sub _search_value {
672 0     0     my($self, $key) = @_;
673 0 0         return unless defined $key;
674 0           $key = lc $key;
675 0 0         return $self->{"_$key"}
676             if defined $self->{"_$key"};
677 0 0 0       return $self->value->{"-$key"}
      0        
678             if defined $self->value
679             and ref($self->value) =~ /hash/i
680             and defined $self->value->{"-$key"};
681 0 0         return $self->safe_value($key)
682             if defined $self->_qualify_value({"-$key"=>$self->safe_value($key)});
683 0           return;
684             }
685              
686             =head2 _next_child_id
687              
688             =over
689              
690             =item
691              
692             Gets the ID for the next child.
693              
694             =item Purpose
695              
696             Provide support for children identification
697              
698             =item Returns
699              
700             The ID (I<str>) or C<undef> if the ID of the current Rule is not set.
701              
702             =back
703              
704             =cut
705              
706             sub _next_child_id {
707 0     0     my $self = shift;
708 0 0         return unless defined $self->id;
709 0   0       $self->{'_children_id'} ||= 1;
710 0           return $self->id . "." . $self->{'_children_id'}++;
711             }
712              
713             1;