Merge pull request #5163 from solgenomics/audit-error-checking
[sgn.git] / lib / CXGN / Fieldbook / TraitProps.pm
blobd4c56fdd682e70e026a85723f443b54bbfe1fab1
1 package CXGN::Fieldbook::TraitProps;
3 =head1 NAME
5 CXGN::Fieldbook::TraitProps - a module to store trait properties in the database.
7 =head1 USAGE
9 my $trait_props = CXGN::Fieldbook::TraitProps->new({ chado_schema => $chado_schema, db_name => $db_name, trait_names_and_props => \@trait_props_data, overwrite => 1, });
10 my $validate = $trait_props->validate(); #returns true if the trait props are valid and can be stored and returns false otherwise.
11 my $store = $trait_props->store(); #returns true if the trait props are stored and returns false otherwise.
13 =head1 DESCRIPTION
15 Stores trait properties in the database to build trait files to use in Fieldbook data collection
17 =head1 AUTHORS
19 Jeremy D. Edwards (jde22@cornell.edu)
21 =cut
23 use Moose;
24 use MooseX::FollowPBP;
25 use Moose::Util::TypeConstraints;
26 use Try::Tiny;
27 use CXGN::Cvterm;
29 has 'chado_schema' => (
30 is => 'ro',
31 isa => 'DBIx::Class::Schema',
32 required => 1,
34 has 'db_name' => (
35 is => 'ro',
36 isa => 'Str',
37 required => 1,
39 has 'trait_names_and_props' => (
40 is => 'ro',
41 isa => 'ArrayRef[HashRef[Str]]',
42 required => 1,
44 has 'overwrite' => (
45 is => 'ro',
46 isa => 'Str',
47 required => 0,
49 has 'is_test_run' => (
50 is => 'ro',
51 isa => 'Str',
52 required => 0,
55 sub _get_cvterms {
56 my $self = shift;
57 my $chado_schema = $self->get_chado_schema();
58 my %cvterms;
60 my @trait_property_names = qw(
61 trait_format
62 trait_default_value
63 trait_minimum
64 trait_maximum
65 trait_details
66 trait_categories
69 my $cv = $chado_schema->resultset("Cv::Cv")
70 ->find_or_create({
71 name => 'trait_property',
72 });
73 $cv->insert;
75 foreach my $property_name (@trait_property_names) {
77 $cvterms{$property_name} = $chado_schema->resultset("Cv::Cvterm")
78 ->create_with({
79 name => $property_name,
80 cv => 'trait_property',
81 });
84 return \%cvterms;
89 sub validate {
90 my $self = shift;
91 my $chado_schema = $self->get_chado_schema();
93 my $db_rs = $chado_schema->resultset("General::Db")->search( { 'me.name' => $self->get_db_name() });
95 if (!$db_rs->first()) {
96 print STDERR "Could not find trait ontology database: ".$self->get_db_name()."\n";
97 return;
100 my $cvterms = $self->_get_cvterms();
102 my @trait_props_data = @{$self->get_trait_names_and_props()};
104 if (scalar @trait_props_data == 0) {
105 print STDERR "No trait props supplied\n";
106 return;
110 foreach my $trait_props (@trait_props_data) {
111 if (!$trait_props->{'trait_name'}) {
112 print STDERR "Bad data structure for trait properties: no trait_name\n";
113 return;
115 my $trait_name = $trait_props->{'trait_name'};
117 my $accession;
119 if ($trait_name =~ /(.*)\|(.*$)/) {
120 $trait_name = $1;
121 $accession = $2;
124 print STDERR "Working with trait $trait_name, accession $accession\n";
125 my $trait_cvterm;
127 if ($accession) {
128 my $cvterm = CXGN::Cvterm->new( { schema => $chado_schema, accession => $accession });
129 $trait_cvterm = $cvterm->cvterm();
131 if (!$cvterm) {
132 print STDERR "Could not find trait $trait_name (with $accession)\n";
133 return;
137 #make sure that the trait name is valid
138 else {
139 $trait_cvterm = $chado_schema->resultset("Cv::Cvterm")
140 ->find( {
141 'dbxref.db_id' => $db_rs->first()->db_id(),
142 'name'=> $trait_name,
145 'join' => 'dbxref'
148 if (!$trait_cvterm) {
149 print STDERR "Could not find trait $trait_name\n";
150 return;
153 #make sure that the trait prop names are valid
154 foreach my $prop_name (keys %{$trait_props}) {
155 if ($prop_name ne 'trait_name') {
156 if (!$cvterms->{$prop_name}) {
157 print STDERR "Bad data structure for trait properties: $prop_name is not valid";
158 return;
161 my $prop_cvterm = $cvterms->{$prop_name};
163 #check for an existing prop of the same name
164 my $cvtermprop_search = $trait_cvterm
165 ->search_related('cvtermprops', {
166 'type_id' => $prop_cvterm->cvterm_id(),
170 if ($cvtermprop_search->count() > 1) {
171 print STDERR "More than one cvtermprop for trait $trait_name with property $prop_name\n";
172 return;
175 if ($cvtermprop_search->count() == 1) {
176 if (!$self->get_overwrite()) {
177 print STDERR "A cvtermprop for trait $trait_name with property $prop_name already exists\n";
178 return;
186 return 1;
190 sub store {
191 my $self = shift;
192 my $chado_schema = $self->get_chado_schema();
193 my $test_success;
195 my $db_rs = $chado_schema->resultset("General::Db")->search( { 'me.name' => $self->get_db_name() });
197 if (!$db_rs) {
198 print STDERR "Could not find trait ontology database: ".$self->get_db_name()."\n";
199 return;
202 my $cvterms = $self->_get_cvterms();
204 my @trait_props_data = @{$self->get_trait_names_and_props()};
206 my $coderef = sub {
208 foreach my $trait_props (@trait_props_data) {
211 my $trait_name = $trait_props->{'trait_name'};
212 my $accession;
214 if ($trait_name =~ /(.*)\|(.*$)/) {
215 $trait_name = $1;
216 $accession = $2;
219 my $trait_cvterm;
221 if ($accession) {
222 my $cvterm = CXGN::Cvterm->new( { schema => $chado_schema, accession => $accession });
223 $trait_cvterm = $cvterm->cvterm();
225 if (!$cvterm) {
226 print STDERR "Could not find trait $trait_name (with $accession)\n";
227 return;
230 else {
231 #get the cvterm for the trait
232 my $trait_cvterm = $chado_schema->resultset("Cv::Cvterm")
233 ->find( {
234 'dbxref.db_id' => $db_rs->first()->db_id(),
235 'name'=> $trait_name,
238 'join' => 'dbxref'
243 foreach my $prop_name (keys %{$trait_props}) {
244 if ($prop_name ne 'trait_name') {
246 my $prop_cvterm = $cvterms->{$prop_name};
248 my $trait_prop_value = $trait_props->{$prop_name};
250 #check for an existing prop of the same name
251 my $cvtermprop_search = $trait_cvterm
252 ->search_related('cvtermprops', {
253 'type_id' => $prop_cvterm->cvterm_id(),
257 if ($cvtermprop_search->count() > 1) {
258 die("More that one cvtermprop for trait $trait_name with property $prop_name\n");
261 #if the trait property already exists, update it overwrite is true or die if false
262 if ($cvtermprop_search->count() == 1) {
263 if ($self->get_overwrite()) {
264 my $found_cvtermprop = $cvtermprop_search->first();
265 $found_cvtermprop->update({value => $trait_prop_value});
266 } else {
267 die("A trait with property $prop_name already exists\n");
269 } else {
270 $trait_cvterm
271 ->find_or_create_related('cvtermprops',{
272 'value' => $trait_prop_value,
273 'type_id' => $prop_cvterm->cvterm_id(),
282 if ($self->get_is_test_run()) {
283 $test_success = 1;
284 die("\nTest run success. Rolling back\n\n");
290 my $transaction_error;
292 try {
293 $chado_schema->txn_do($coderef);
294 } catch {
295 $transaction_error = $_;
298 if ($transaction_error) {
299 if ($self->get_is_test_run()) {
300 if ($test_success) {
301 print STDERR "test success (rolling back)\n";
302 } else {
303 print STDERR "test error\n$transaction_error\n";
305 } else {
306 print STDERR "\nTransaction error storing trait props: $transaction_error\n";
308 return;
311 return 1;
315 #######
317 #######