File Coverage

blib/lib/Bio/ConnectDots/DotQuery/Constraint.pm
Criterion Covered Total %
statement 18 104 17.3
branch 0 68 0.0
condition 0 20 0.0
subroutine 6 19 31.5
pod 0 13 0.0
total 24 224 10.7


line stmt bran cond sub pod time code
1             package Bio::ConnectDots::DotQuery::Constraint;
2 1     1   8 use strict;
  1         2  
  1         242  
3 1     1   7 use vars qw(@ISA @AUTO_ATTRIBUTES @OTHER_ATTRIBUTES %SYNONYMS %DEFAULTS);
  1         2  
  1         97  
4 1     1   5 use Class::AutoClass;
  1         2  
  1         19  
5 1     1   5 use Bio::ConnectDots::Util;
  1         2  
  1         287  
6 1     1   6 use Bio::ConnectDots::Parser;
  1         2  
  1         19  
7 1     1   1636 use Bio::ConnectDots::DotQuery::Term;
  1         3  
  1         1662  
8             @ISA = qw(Class::AutoClass);
9              
10             @AUTO_ATTRIBUTES=qw(_term _op constants);
11             %SYNONYMS=();
12             @OTHER_ATTRIBUTES=qw(term op ct_alias cs_alias labels label_ids termlist);
13             %DEFAULTS=(_op=>'=');
14             Class::AutoClass::declare(__PACKAGE__);
15              
16             # legal formats:
17             # 1) Old ConnectorTable format: ARRAY or HASH of
18             # column =>[label], [label constant] or [label op constant]
19             # NOTE: Old ConnectorSet format NOT supported, because it conflicts with
20             # new ARRAY of output strings
21             # 2) single query string which may include multiple constraints AND'ed together
22             # 3) single Constraint object
23             # 4) ARRAY of (1) query strings and (2) Constraint objects
24              
25             sub parse {
26 0     0 0   my($class,$constraints)=@_;
27 0           my $parsed=[];
28 0           my $parser=new Bio::ConnectDots::Parser;
29             # ARRAY is old form if even number of elements, element 0 is scalar, element 1 is ARRAY
30 0 0 0       if (('ARRAY' eq ref $constraints) && @$constraints &&
      0        
      0        
      0        
31             @$constraints%2==0 && !ref $constraints->[0] && 'ARRAY' eq ref $constraints->[1]) {
32 0           my $hash;
33 0           while(@$constraints) {
34 0           my($column,$constraint)=(shift @$constraints,shift @$constraints);
35 0   0       my $constraint_list=$hash->{$column} || ($hash->{$column}=[]);
36 0           push(@$constraint_list,$constraint);
37             }
38 0           $constraints=$hash;
39             }
40             # HASH is always old form. Old form ARRAY turned into HASH in 'if' above
41             # Note 'if' -- not 'elsif'
42 0 0         if ('HASH' eq ref $constraints) {
    0          
    0          
    0          
43 0           while (my($column,$constraint_list)=each %$constraints) {
44 0 0         $constraint_list=[$constraint_list] unless 'ARRAY' eq ref $constraint_list->[0];
45 0           for my $constraint (@$constraint_list) {
46 0           my($labels,$op,$constant);
47 0 0 0       $class->throw("Illegal constraint format ".value_as_string($constraint).
48             ": must have 1-3 elements")
49             unless @$constraint && @$constraint<=3;
50 0 0         ($labels)=@$constraint if @$constraint==1;
51 0 0         ($labels,$constant)=@$constraint if @$constraint==2;
52 0 0         ($labels,$op,$constant)=@$constraint if @$constraint==3;
53 0           $constant=$parser->parse_constant_value($constant); # handle constant lists
54 0           push(@$parsed,
55             $class->new(-termlist=>[$column,$labels],-op=>$op,-constant=>$constant));
56             }
57             }
58             } elsif (!ref $constraints) { # string
59 0           push(@$parsed,$class->parse_string($constraints,$parser));
60             } elsif (UNIVERSAL::isa($constraints,__PACKAGE__)) {
61 0           push(@$parsed,$constraints);
62             } elsif ('ARRAY' eq ref $constraints) { # new form ARRAY
63 0           for my $constraint (@$constraints) {
64 0 0         if (!ref $ $constraint) {
    0          
65 0           push(@$parsed,$class->parse_string($constraint,$parser));
66             } elsif (UNIVERSAL::isa($constraint,__PACKAGE__)) {
67 0           push(@$parsed,$constraint);
68             } else {
69 0           $class->throw("llegal constraint format ".value_as_string($constraint).
70             ": must be string or Constraint object to appear in new ARRAY format");
71             }
72             }
73             } else {
74 0           $class->throw("Unrecognized constraint form ".value_as_string($constraints).
75             ": strange type! Not scalar, Constraint object, ARRAY, or HASH");
76             }
77 0 0         wantarray? @$parsed: $parsed
78             }
79             sub parse_string {
80 0     0 0   my($class,$constraints,$parser)=@_;
81 0           my $parsed=[];
82 0           my $parsed_constraints=$parser->parse_constraints($constraints);
83 0 0         if ($parsed_constraints) {
84 0           for my $constraint (@$parsed_constraints) {
85 0           my($term,$op,$constant)=@$constraint{qw(term op constant)};
86 0           push(@$parsed,
87             $class->new(-termlist=>$term,-op=>$op,-constants=>$constant));
88             }
89             }
90 0 0         wantarray? @$parsed: $parsed;
91             }
92              
93             sub normalize {
94 0     0 0   my($self)=@_;
95 0           $self->term->normalize;
96 0           my $op=$self->op;
97 0           my $constants=$self->constants;
98 0 0         $op or $op=$constants? '=': 'EXISTS';
    0          
99              
100 0 0         if ('ARRAY' eq ref $constants) {
    0          
101 0           $self->throw("Invalid constraint".$self->as_string.": nested list constants are not supported")
102 0 0         if grep {'ARRAY' eq ref $_} @$constants;
103 0 0         $self->throw("Invalid constraint".$self->as_string.": empty list constants are not supported")
104             unless @$constants;
105             # normalize ops with list constants
106 0 0         if ($op eq '=') {
    0          
    0          
    0          
107 0           $self->op('IN');
108             } elsif ($op eq "!=") {
109 0           $self->op('NOT IN');
110             } elsif ($op=~/
111 0           my $max=maxb(@$constants); # does numeric or alpha max as appropriate
112 0           $self->constants([$max]);
113             } elsif ($op=~/>/) { # range op: just compare to end of range
114 0           my $min=minb(@$constants); # does numeric or alpha min as appropriate
115 0           $self->constants([$min]);
116             }
117             } elsif (!ref $constants) { # change single value to list
118 0 0 0       $self->throw("Invalid constraint".$self->as_string.": no constant provided")
119             unless $op eq 'EXISTS' || defined $constants;
120 0           $constants=$self->constants([$constants]);
121             } else {
122 0           $self->throw("Invalid constraint".$self->as_string.": strange type!");
123             }
124 0           $self;
125             }
126              
127             sub term {
128 0     0 0   my $self=shift @_;
129 0 0         my $term=@_? $self->_term($_[0]): $self->_term;
130 0 0         $term or $term=$self->_term(new Bio::ConnectDots::DotQuery::Term);
131 0           $term;
132             }
133             sub op {
134 0     0 0   my $self=shift @_;
135 0 0         my $op=@_? $self->_op($_[0]): $self->_op;
136 0 0         $op or $op='=';
137 0           $op;
138             }
139 0     0 0   sub cs {$_[0]->term->cs;}
140 0     0 0   sub cs_id {$_[0]->term->cs_id;}
141 0     0 0   sub cs_name {$_[0]->term->cs_name;}
142             sub column {
143 0     0 0   my $self=shift @_;
144 0 0         my $column=@_? $self->term->column($_[0]): $self->term->column;
145 0           $column;
146             }
147             sub labels {
148 0     0 0   my $self=shift @_;
149 0 0         my $labels=@_? $self->term->labels($_[0]): $self->term->labels;
150 0           $labels;
151             }
152             sub label_ids {
153 0     0 0   my $self=shift @_;
154 0 0         my $label_ids=@_? $self->term->label_ids($_[0]): $self->term->label_ids;
155 0           $label_ids;
156             }
157             sub termlist {
158 0     0 0   my $self=shift @_;
159 0 0         my $termlist=@_? $self->term->termlist($_[0]): $self->term->termlist;
160 0           $termlist;
161             }
162             sub as_string {
163 0     0 0   my($self)=@_;
164 0           my $term=$self->term->as_string;
165 0           my $op=$self->op;
166 0           my $constants=value_as_string($self->constants);
167 0           return "$term $op $constants";
168             }
169              
170             1;
171