File Coverage

blib/lib/Bio/Chado/Schema/Util.pm
Criterion Covered Total %
statement 48 50 96.0
branch 15 32 46.8
condition 5 14 35.7
subroutine 5 5 100.0
pod 1 1 100.0
total 74 102 72.5


line stmt bran cond sub pod time code
1             package Bio::Chado::Schema::Util;
2             BEGIN {
3 6     6   161 $Bio::Chado::Schema::Util::AUTHORITY = 'cpan:RBUELS';
4             }
5             BEGIN {
6 6     6   108 $Bio::Chado::Schema::Util::VERSION = '0.08001'; # TRIAL
7             }
8 6     6   30 use strict;
  6         23  
  6         223  
9 6     6   369 use Carp::Clan qr/^Bio::Chado::Schema/;
  6         1256  
  6         59  
10              
11             sub create_properties {
12 1     1 1 5 my ($class, %args) = @_;
13              
14             #check for required args
15             $args{prop_relation_name} or confess "must provide $_ arg"
16 1   33     8 for qw/ row prop_relation_name properties options/;
17              
18 1         3 my $self = delete $args{row};
19 1         2 my $props = delete $args{properties};
20 1         3 my $opts = delete $args{options};
21 1         3 my $prop_relation_name = delete $args{prop_relation_name};
22              
23 1 50       4 %args and confess "invalid option(s): ".join(', ', sort keys %args);
24              
25             # normalize the props to hashrefs
26 1         3 foreach (values %$props) {
27 1 50       6 $_ = { value => $_ } unless ref eq 'HASH';
28             }
29              
30             # process opts
31 1   50     3 $opts ||= {};
32 1 50       5 defined $opts->{cv_name} or confess 'must provide a cv_name in options';
33             $opts->{db_name} = 'null'
34 1 50       5 unless defined $opts->{db_name};
35             $opts->{dbxref_accession_prefix} = 'autocreated:'
36 1 50       4 unless defined $opts->{dbxref_accession_prefix};
37              
38 1         4 my $schema = $self->result_source->schema;
39              
40 1         13 my $prop_cv = do {
41 1         5 my $cvrs = $schema->resultset('Cv::Cv');
42 1 50       329 my $find_or_create = $opts->{autocreate} ? 'find_or_create' : 'find';
43             $cvrs->$find_or_create({ name => $opts->{cv_name}},
44 1 50       7 { key => 'cv_c1' })
45             or croak "cv '$opts->{cv_name}' not found and autocreate option not passed, cannot continue";
46             };
47              
48 1         3639 my $prop_db; #< set as needed below
49              
50             # find/create cvterms and dbxrefs for each of our featureprops,
51             # and remember them in %propterms
52             my %propterms;
53 1         5 foreach my $propname (keys %$props) {
54 1         17 my $existing_cvterm = $propterms{$propname} =
55             $prop_cv->find_related('cvterms',
56             { name => $propname,
57             is_obsolete => 0,
58             },
59             { key => 'cvterm_c1' },
60             );
61              
62             # if there is no existing cvterm for this in the prop table,
63             # and we have the autocreate flag set true, then create a
64             # cvterm, dbxref, and db for it if necessary
65 1 50       5466 unless( $existing_cvterm ) {
66             $opts->{autocreate}
67 1 50       21 or croak "cvterm not found for property '$propname', and autocreate option not passed, cannot continue";
68              
69             # look up the db object if we don't already have it, now
70             # that we know we need it
71             $prop_db ||=
72             $self->result_source->schema
73             ->resultset('General::Db')
74             ->find_or_create( { name => $opts->{db_name} },
75 1   33     8 { key => 'db_c1' }
76             );
77              
78             # find or create the dbxref for this cvterm we are about
79             # to create
80 1         3029 my $dbx_acc = $opts->{dbxref_accession_prefix}.$propname;
81 1   33     36 my $dbxref =
82             $prop_db->search_related( 'dbxrefs',
83             { accession => $dbx_acc },
84             { order_by => { -desc => ['version'] } }
85             )
86             ->first
87             || $prop_db->create_related( 'dbxrefs', { accession => $dbx_acc,
88             version => 1,
89             });
90              
91             # look up any definition we might have been given for this
92             # propname, so we can insert it if given
93 1         6569 my $def = $opts->{definitions}->{$propname};
94              
95 1 50       136 $propterms{$propname} =
96             $prop_cv->create_related('cvterms',
97             { name => $propname,
98             is_obsolete => 0,
99             dbxref_id => $dbxref->dbxref_id,
100             $def ? (definition => $def) : (),
101             }
102             );
103             }
104             }
105              
106 1         2317 my %props;
107 1         6 while( my ($propname,$propval) = each %$props ) {
108              
109 1 50       28 my $data = ref $propval
110             ? {%$propval}
111             : { value => $propval };
112              
113 1         30 $data->{type_id} = $propterms{$propname}->cvterm_id;
114              
115              
116             # decide whether to skip creating this prop
117             my $skip_creation = $opts->{allow_duplicate_values}
118             ? 0
119             : $self->search_related( $prop_relation_name,
120             { type_id => $data->{type_id},
121             value => $data->{value},
122             })
123 1 50       23 ->count;
124              
125              
126 1 50       5054 unless( $skip_creation ) {
127             #if rank is defined
128 1 50 33     28 if ($opts->{rank} && defined $opts->{rank} ) {
129             my ($existing_prop) = $self->search_related( $prop_relation_name,
130             {type_id =>$data->{type_id},
131             rank => $opts->{rank}
132 1         7 });
133 1 50       2239 warn "Property " . $existing_prop->value() . " already exists with rank " . $opts->{rank} . ". skipping! \n" if defined $existing_prop;
134 1         17 $data->{rank} = $opts->{rank};
135              
136             } else {
137             # find highest rank for props of this type
138             my $max_rank= $self->search_related( $prop_relation_name,
139             { type_id =>$data->{type_id} }
140 0         0 )->get_column('rank')->max;
141 0 0       0 $data->{rank} = defined $max_rank ? $max_rank + 1 : 0;
142              
143             }
144 1         20 $props{$propname} = $self->find_or_create_related( $prop_relation_name,
145             $data
146             );
147             }
148             }
149 1         8443 return \%props;
150             }
151              
152             1;
153              
154              
155              
156             =pod
157              
158             =encoding utf-8
159              
160             =head1 NAME
161              
162             Bio::Chado::Schema::Util
163              
164             =head1 SYNOPSIS
165              
166             sub create_organismprops {
167             my ($self, $props, $opts) = @_;
168              
169             # process opts
170             $opts ||= {};
171             $opts->{cv_name} = 'organism_property'
172             unless defined $opts->{cv_name};
173              
174             return Bio::Chado::Schema::Util->create_props
175             ( properties => $props,
176             options => $opts,
177             row => $self,
178             prop_relation_name => 'organismprops',
179             );
180             }
181              
182             =head1 DESCRIPTION
183              
184             Helper functions used by several schema classes.
185              
186             Important Note:
187             This package is located in the Schema.pm file as secondary package
188             and it haven't a file for itself. Nevertheless, the use will be the same.
189              
190             =head1 NAME
191              
192             Bio::Chado::Schema::Util - utility functions shared by Bio::Chado::Schema objects
193              
194             =head1 PACKAGE METHODS
195              
196             =head2 create_properties
197              
198             Usage: *::Util->create_properties( row => $self,
199             properties => { baz => 2, foo => 'bar' },
200             options => { cv_name => autocreate => 0, ...},
201             prop_relation_name => 'organismprops',
202             );
203              
204             Desc : Chado has a number of prop tables with a similar
205             structure. This utility function is used by a number of
206             modules to create properties in these kinds of tables.
207              
208             Args : row => the DBIC row object to create properties for,
209             prop_relation_name => the DBIC relation name for the
210             properties table to operate on,
211             e.g. 'featureprops',
212             properties => hashref of { propname => value, ...},
213             options => options hashref as:
214             {
215             autocreate => 0,
216             (optional) boolean, if passed, automatically create cv,
217             cvterm, and dbxref rows if one cannot be found for the
218             given featureprop name. Default false.
219              
220             cv_name => cv.name to use for the given featureprops.
221             Defaults to 'feature_property',
222              
223             db_name => db.name to use for autocreated dbxrefs,
224             default 'null',
225              
226             allow_duplicate_values => default false.
227             If true, allow duplicate instances of the same cvterm
228             and value in the properties of the feature. Duplicate
229             values will have different ranks.
230              
231             dbxref_accession_prefix => optional, default
232             'autocreated:',
233             definitions => optional hashref of:
234             { cvterm_name => definition,
235             }
236             to load into the cvterm table when autocreating cvterms
237             }
238             Ret : hashref of { propname => new row object in property table }
239              
240             =head1 AUTHOR
241              
242             Robert Buels,
243              
244             Naama Menda,
245              
246             =head1 COPYRIGHT & LICENSE
247              
248             Copyright 2009 Boyce Thompson Institute for Plant Research
249              
250             This program is free software; you can redistribute it and/or modify
251             it under the same terms as Perl itself.
252              
253             =head1 AUTHOR
254              
255             Robert Buels
256              
257             =head1 COPYRIGHT AND LICENSE
258              
259             This software is copyright (c) 2011 by Robert Buels.
260              
261             This is free software; you can redistribute it and/or modify it under
262             the same terms as the Perl 5 programming language system itself.
263              
264             =cut
265              
266              
267             __END__