Merge pull request #2383 from solgenomics/dauglyon-patch-1
[sgn.git] / lib / CXGN / Fieldbook / TraitProps.pm
blob439782afb19f77186ee8597d89a20bfc2991b426
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;
28 has 'chado_schema' => (
29 is => 'ro',
30 isa => 'DBIx::Class::Schema',
31 required => 1,
33 has 'db_name' => (
34 is => 'ro',
35 isa => 'Str',
36 required => 1,
38 has 'trait_names_and_props' => (
39 is => 'ro',
40 isa => 'ArrayRef[HashRef[Str]]',
41 required => 1,
43 has 'overwrite' => (
44 is => 'ro',
45 isa => 'Str',
46 required => 0,
48 has 'is_test_run' => (
49 is => 'ro',
50 isa => 'Str',
51 required => 0,
54 sub _get_cvterms {
55 my $self = shift;
56 my $chado_schema = $self->get_chado_schema();
57 my %cvterms;
59 my @trait_property_names = qw(
60 trait_format
61 trait_default_value
62 trait_minimum
63 trait_maximum
64 trait_details
65 trait_categories
68 my $cv = $chado_schema->resultset("Cv::Cv")
69 ->find_or_create({
70 name => 'trait_property',
71 });
72 $cv->insert;
74 foreach my $property_name (@trait_property_names) {
76 $cvterms{$property_name} = $chado_schema->resultset("Cv::Cvterm")
77 ->create_with({
78 name => $property_name,
79 cv => 'trait_property',
80 });
83 return \%cvterms;
88 sub validate {
89 my $self = shift;
90 my $chado_schema = $self->get_chado_schema();
92 my $db_rs = $chado_schema->resultset("General::Db")->search( { 'me.name' => $self->get_db_name() });
94 if (!$db_rs->first()) {
95 print STDERR "Could not find trait ontology database: ".$self->get_db_name()."\n";
96 return;
99 my $cvterms = $self->_get_cvterms();
101 my @trait_props_data = @{$self->get_trait_names_and_props()};
103 if (scalar @trait_props_data == 0) {
104 print STDERR "No trait props supplied\n";
105 return;
109 foreach my $trait_props (@trait_props_data) {
110 if (!$trait_props->{'trait_name'}) {
111 print STDERR "Bad data structure for trait properties: no trait_name\n";
112 return;
114 my $trait_name = $trait_props->{'trait_name'};
116 #make sure that the trait name is valid
117 my $trait_cvterm;
118 $trait_cvterm = $chado_schema->resultset("Cv::Cvterm")
119 ->find( {
120 'dbxref.db_id' => $db_rs->first()->db_id(),
121 'name'=> $trait_name,
124 'join' => 'dbxref'
127 if (!$trait_cvterm) {
128 print STDERR "Could not find trait $trait_name\n";
129 return;
132 #make sure that the trait prop names are valid
133 foreach my $prop_name (keys %{$trait_props}) {
134 if ($prop_name ne 'trait_name') {
135 if (!$cvterms->{$prop_name}) {
136 print STDERR "Bad data structure for trait properties: $prop_name is not valid";
137 return;
140 my $prop_cvterm = $cvterms->{$prop_name};
142 #check for an existing prop of the same name
143 my $cvtermprop_search = $trait_cvterm
144 ->search_related('cvtermprops', {
145 'type_id' => $prop_cvterm->cvterm_id(),
149 if ($cvtermprop_search->count() > 1) {
150 print STDERR "More than one cvtermprop for trait $trait_name with property $prop_name\n";
151 return;
154 if ($cvtermprop_search->count() == 1) {
155 if (!$self->get_overwrite()) {
156 print STDERR "A cvtermprop for trait $trait_name with property $prop_name already exists\n";
157 return;
165 return 1;
169 sub store {
170 my $self = shift;
171 my $chado_schema = $self->get_chado_schema();
172 my $test_success;
174 my $db_rs = $chado_schema->resultset("General::Db")->search( { 'me.name' => $self->get_db_name() });
176 if (!$db_rs) {
177 print STDERR "Could not find trait ontology database: ".$self->get_db_name()."\n";
178 return;
181 my $cvterms = $self->_get_cvterms();
183 my @trait_props_data = @{$self->get_trait_names_and_props()};
185 my $coderef = sub {
187 foreach my $trait_props (@trait_props_data) {
189 my $trait_name = $trait_props->{'trait_name'};
191 #get the cvterm for the trait
192 my $trait_cvterm = $chado_schema->resultset("Cv::Cvterm")
193 ->find( {
194 'dbxref.db_id' => $db_rs->first()->db_id(),
195 'name'=> $trait_name,
198 'join' => 'dbxref'
202 foreach my $prop_name (keys %{$trait_props}) {
203 if ($prop_name ne 'trait_name') {
205 my $prop_cvterm = $cvterms->{$prop_name};
207 my $trait_prop_value = $trait_props->{$prop_name};
209 #check for an existing prop of the same name
210 my $cvtermprop_search = $trait_cvterm
211 ->search_related('cvtermprops', {
212 'type_id' => $prop_cvterm->cvterm_id(),
216 if ($cvtermprop_search->count() > 1) {
217 die("More that one cvtermprop for trait $trait_name with property $prop_name\n");
220 #if the trait property already exists, update it overwrite is true or die if false
221 if ($cvtermprop_search->count() == 1) {
222 if ($self->get_overwrite()) {
223 my $found_cvtermprop = $cvtermprop_search->first();
224 $found_cvtermprop->update({value => $trait_prop_value});
225 } else {
226 die("A trait with property $prop_name already exists\n");
228 } else {
229 $trait_cvterm
230 ->find_or_create_related('cvtermprops',{
231 'value' => $trait_prop_value,
232 'type_id' => $prop_cvterm->cvterm_id(),
241 if ($self->get_is_test_run()) {
242 $test_success = 1;
243 die("\nTest run success. Rolling back\n\n");
249 my $transaction_error;
251 try {
252 $chado_schema->txn_do($coderef);
253 } catch {
254 $transaction_error = $_;
257 if ($transaction_error) {
258 if ($self->get_is_test_run()) {
259 if ($test_success) {
260 print STDERR "test success (rolling back)\n";
261 } else {
262 print STDERR "test error\n$transaction_error\n";
264 } else {
265 print STDERR "\nTransaction error storing trait props: $transaction_error\n";
267 return;
270 return 1;
274 #######
276 #######