File Coverage

blib/lib/Bio/Polloc/Rule/boolean.pm
Criterion Covered Total %
statement 18 92 19.5
branch 0 54 0.0
condition 0 17 0.0
subroutine 7 13 53.8
pod 6 6 100.0
total 31 182 17.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Bio::Polloc::Rule::boolean - A rule of type boolean operator
4              
5             =head1 AUTHOR - Luis M. Rodriguez-R
6              
7             Email lmrodriguezr at gmail dot com
8              
9             =cut
10              
11             package Bio::Polloc::Rule::boolean;
12 3     3   15 use base qw(Bio::Polloc::RuleI);
  3         7  
  3         264  
13 3     3   14 use strict;
  3         10  
  3         139  
14 3     3   16 use Bio::Polloc::Polloc::IO;
  3         6  
  3         61  
15 3     3   15 use Bio::Polloc::LocusI;
  3         4  
  3         56  
16 3     3   14 use Bio::SeqIO;
  3         5  
  3         3372  
17             our $VERSION = 1.0503; # [a-version] from Bio::Polloc::Polloc::Version
18              
19              
20             =head1 APPENDIX
21              
22             Methods provided by the package
23              
24             =cut
25              
26             sub new {
27 0     0 1 0 my($caller,@args) = @_;
28 0         0 my $self = $caller->SUPER::new(@args);
29 0         0 $self->_initialize(@args);
30 0         0 return $self;
31             }
32              
33             =head2 execute
34              
35             =head3 Arguments
36              
37             =over
38              
39             =item -seq I<Bio::Seq or Bio::SeqIO object>
40              
41             The input sequence(s).
42              
43             =back
44              
45             =head3 Returns
46              
47             An array reference populated with Bio::Polloc::Locus::* objects
48              
49             =head3 Throws
50              
51             L<Bio::Polloc::Polloc::UnexpectedException> if the operator is not supported or
52             L<Bio::Polloc::Polloc::Error> if the rule is not within a rule set (a
53             L<Bio::Polloc::RuleIO> object).
54              
55             =cut
56              
57             sub execute {
58 0     0 1 0 my($self,@args) = @_;
59 0         0 my($seq) = $self->_rearrange([qw(SEQ)], @args);
60 0 0       0 $self->throw("You must provide a sequence to evaluate the rule", $seq) unless $seq;
61            
62             # For Bio::SeqIO objects
63 0 0       0 if($seq->isa('Bio::SeqIO')){
64 0         0 my @feats = ();
65 0         0 while(my $s = $seq->next_seq){
66 0         0 push(@feats, @{$self->execute(-seq=>$s)})
  0         0  
67             }
68 0 0       0 return wantarray ? @feats : \@feats;
69             }
70            
71             # Preset the environment
72 0 0       0 $self->throw("Impossible to qualify a boolean outside a Rule Set (Bio::Polloc::RuleIO)", $self)
73             unless defined $self->ruleset;
74 0 0       0 $self->throw("Illegal object as Rule Set", $self->ruleset)
75             unless $self->ruleset->isa('Bio::Polloc::RuleIO');
76 0         0 $self->value($self->value); # To implicitly call _qualify_value
77            
78 0 0       0 $self->throw("Illegal class of sequence '".ref($seq)."'", $seq)
79             unless $seq->isa('Bio::Seq');
80 0 0 0     0 $self->throw("Impossible to compare with '".$self->operator.
81             "' on undefined second object", $self->rule2)
82             if $self->operator and not defined $self->rule2;
83            
84 0         0 my @feats = ();
85 0         0 for my $feat_obj (@{$self->rule1->execute(-seq=>$seq)}){
  0         0  
86 0 0 0     0 if($self->operator eq 'and' or $self->operator eq 'not'){
    0 0        
87             # And or Not
88 0         0 my $sbj_seq = Bio::Seq->new( -display_id => $seq->display_id,
89             -seq => $seq->subseq($feat_obj->from, $feat_obj->to) );
90 0         0 my @feat_sbjs = @{ $self->rule2->execute(-seq=>$sbj_seq) };
  0         0  
91 0 0 0     0 next if $#feat_sbjs<0 and $self->operator eq 'and';
92 0 0 0     0 next if $#feat_sbjs>=0 and $self->operator eq 'not';
93 0 0       0 if($self->operator eq 'not'){
94             # Not
95 0         0 $feat_obj->comments('Not ' . $self->rule2->stringify);
96 0         0 push @feats, $feat_obj;
97             }else{
98             # And
99 0         0 my $comm = 'And ' . $self->rule2->stringify . '{';
100 0         0 for my $feat_sbj ( @feat_sbjs ){
101 0 0       0 my $ft_comm = defined $feat_sbj->comments ? " (".($feat_sbj->comments).")" : "";
102 0         0 $ft_comm =~ s/[\n\r]+/; /g;
103 0         0 $comm.= $feat_sbj->stringify . $ft_comm . ", ";
104             }
105 0         0 $feat_obj->comments(substr($comm,0,-2) . '}');
106 0         0 push @feats, $feat_obj;
107             }
108             }elsif($self->operator eq 'or' || not defined $self->rule2){
109             # Or or any operation
110 0         0 push @feats, $feat_obj;
111             }else{
112             # Oops!
113 0         0 $self->throw("Unsupported operator",
114             $self->operator, 'Bio::Polloc::Polloc::UnexpectedException');
115             }
116             }
117 0 0       0 if($self->operator eq 'or'){
118             # Or simply adds the two sets of features
119 0         0 push @feats, @{$self->rule2->execute(-seq=>$seq)};
  0         0  
120             }
121            
122 0 0       0 return wantarray ? @feats : \@feats;
123             }
124              
125              
126             =head2 rule1
127              
128             Gets/sets the first rule
129              
130             =head2 Arguments
131              
132             A L<Bio::Polloc::RuleI> object (optional)
133              
134             =head2 Returns
135              
136             L<Bio::Polloc::RuleI> object or C<undef>.
137              
138             =cut
139              
140             sub rule1 {
141 0     0 1 0 my($self,$value) = @_;
142 0 0       0 $self->{'_rule1'} = $value if defined $value;
143 0 0       0 $self->{'_rule1'} = $self->safe_value('rule1') unless defined $self->{'_rule1'};
144 0         0 return $self->{'_rule1'};
145             }
146              
147              
148             =head2 operator
149              
150             Gets/sets the operator
151              
152             =head2 Arguments
153              
154             A string with the operator.
155              
156             =head2 Returns
157              
158             String 'and', 'or', 'not' or C<undef>.
159              
160             =cut
161              
162             sub operator {
163 0     0 1 0 my($self,$value) = @_;
164             # Set by received value
165 0 0       0 if($value){
166 0         0 $value = lc $value;
167 0         0 $value =~ s/\&/and/;
168 0         0 $value =~ s/\|/or/;
169 0         0 $value =~ s/\^/not/;
170 0 0       0 $self->throw("Unsupported operator", $value) if $value !~ /^(and|or|not)$/;
171 0         0 $self->{'_operator'} = $value;
172             }
173            
174             # Set by value()
175 0 0       0 unless($self->{'_operator'}){
176 0         0 my $op = $self->value;
177 0 0       0 $self->operator($op) if $op;
178             }
179              
180             # Set by safe_value()
181 0 0       0 unless($self->{'_operator'}){
182 0         0 my $op = $self->safe_value('operator');
183 0 0       0 $self->operator($op) if $op;
184             }
185            
186             # Return
187 0   0     0 $self->{'_operator'} ||= '';
188 0         0 return $self->{'_operator'};
189             }
190              
191              
192             =head2 rule2
193              
194             Gets/sets the second rule
195              
196             =head2 Arguments
197              
198             A L<Bio::Polloc::RuleI> object (optional).
199              
200             =head2 Returns
201              
202             L<Bio::Polloc::RuleI> object or C<undef>.
203              
204             =cut
205              
206             sub rule2 {
207 0     0 1 0 my($self,$value) = @_;
208 0 0       0 $self->{'_rule2'} = $value if defined $value;
209 0 0       0 $self->{'_rule2'} = $self->safe_value('rule2') unless defined $self->{'_rule2'};
210 0         0 return $self->{'_rule2'};
211             }
212              
213              
214             # Overrides function from Bio::Polloc::RuleI
215             sub stringify_value {
216 0     0 1 0 my ($self,@args) = @_;
217 0         0 my $out = "";
218 0 0       0 return $out unless defined $self->rule1;
219 0         0 $out.= $self->rule1->stringify;
220 0 0       0 return $out unless defined $self->rule2;
221 0         0 $out.= ' ' . $self->operator . ' ' . $self->rule2->stringify ;
222 0         0 return $out;
223             }
224              
225             =head1 INTERNAL METHODS
226              
227             Methods intended to be used only within the scope of Bio::Polloc::*
228              
229             =head2 _qualify_value
230              
231             Implements the C<_qualify_value()> method from the L<Bio::Polloc::RuleI> interface.
232              
233             =head2 Arguments
234              
235             None, the operation should be set using the L<Bio::Polloc::Rule::boolean::rule1()>,
236             L<Bio::Polloc::Rule::boolean::operator()> and L<Bio::Polloc::Rule::boolean::rule2()>
237             functions.
238              
239             =head2 Return
240              
241             The received value.
242              
243             =head2 Note
244              
245             Do not call L<Bio::Polloc::RuleI::value()> with an undefined value, it is the only
246             way to make it crash for booleans.
247              
248             =cut
249              
250             sub _qualify_value {
251 3     3   10 return $_[1];
252             }
253              
254             =head2 _initialize
255              
256             =cut
257              
258             sub _initialize {
259 3     3   14 my($self,@args) = @_;
260 3         23 $self->type('boolean');
261             }
262              
263              
264              
265             1;