Merge pull request #5191 from solgenomics/topic/quality_control
[sgn.git] / lib / CXGN / BrAPI / v2 / Germplasm.pm
blob1d9aa8d0df72a97e06cb03a0553a16855cabce48
1 package CXGN::BrAPI::v2::Germplasm;
3 use Moose;
4 use Data::Dumper;
5 use SGN::Model::Cvterm;
6 use CXGN::Trial;
7 use CXGN::Stock::Search;
8 use CXGN::Stock;
9 use CXGN::BrAPI::v2::ExternalReferences;
10 use CXGN::Chado::Organism;
11 use CXGN::BrAPI::Pagination;
12 use CXGN::BrAPI::JSONResponse;
13 use CXGN::Cross;
14 use Try::Tiny;
15 use JSON;
17 extends 'CXGN::BrAPI::v2::Common';
19 sub search {
20 my $self = shift;
21 my $params = shift;
22 my $c = shift;
24 my $page_size = $self->page_size;
25 my $page = $self->page;
26 my $status = $self->status;
27 my @data_files;
29 my $crop_names_arrayref = $params->{commonCropName} || ($params->{commonCropNames} || ());
30 my $germplasm_names_arrayref = $params->{germplasmName} || ($params->{germplasmNames} || ());
31 my $accession_numbers_arrayref = $params->{accessionNumber} || ($params->{accessionNumbers} || ());
32 my $genera_arrayref = $params->{genus} || ($params->{genera} || ());
33 my $germplasm_ids_arrayref = $params->{germplasmDbId} || ($params->{germplasmDbIds} || ());
34 my $germplasm_puis_arrayref = $params->{germplasmPUI} || ($params->{germplasmPUIs} || ());
35 my $species_arrayref = $params->{species} || ($params->{species} || ());
36 my $synonyms_arrayref = $params->{synonym} || ($params->{synonyms} || ());
37 my $subtaxa = $params->{germplasmSubTaxa}->[0];
38 my $match_method = $params->{matchMethod}->[0] || 'exact';
39 my $collection = $params->{collection} || ($params->{collections} || ());
40 my $study_db_id = $params->{studyDbId} || ($params->{studyDbIds} || ());
41 my $study_names = $params->{studyName} || ($params->{studyNames} || ());
42 my $parent_db_id = $params->{parentDbId} || ($params->{parentDbIds} || ());
43 my $progeny_db_id = $params->{progenyDbId} || ($params->{progenyDbIds} || ());
44 my $external_reference_id_arrayref = $params->{externalReferenceID} || ($params->{externalReferenceIDs} || ());
45 my $external_reference_source_arrayref = $params->{externalReferenceSource} || ($params->{externalReferenceSources} || ());
47 if ( $collection || $progeny_db_id || $parent_db_id ){
48 push @$status, { 'error' => 'The following search parameters are not implemented: collection, parentDbId, progenyDbId' };
51 if ($match_method ne 'exact' && $match_method ne 'wildcard') {
52 push @$status, { 'error' => "matchMethod '$match_method' not recognized. Allowed matchMethods: wildcard, exact. Wildcard allows % or * for multiple characters and ? for single characters." };
54 my $match_type;
55 if ($match_method eq 'exact'){
56 $match_type = 'exactly';
58 if ($match_method eq 'wildcard'){
59 $match_type = 'contains';
62 my $accession_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
64 my $limit = $page_size*($page+1)-1;
65 my $offset = $page_size*$page;
67 my %stock_props = (
68 'accession number'=>1,
69 'acquisition date'=>1,
70 'biological status of accession code'=>1,
71 'country of origin'=>1,
72 'donor'=>1,
73 'donor institute'=>1,
74 'institute code'=>1,
75 'institute name'=>1,
76 'ncbi_taxonomy_id'=>1,
77 'PUI'=>1,
78 'seed source'=>1,
79 'stock_additional_info'=>1,
80 'type of germplasm storage code'=>1 );
82 ## Additional stock props for additional info.
83 my %additional_stock_props;
84 my @editable_stock_props = SGN::Context->new()->get_conf('editable_stock_props') ? split ',', SGN::Context->new()->get_conf('editable_stock_props'): undef;
86 my %editable_stock_props = map { $_=>1 } @editable_stock_props;
88 foreach (keys %editable_stock_props){
89 if(!%stock_props{$_}){
90 $additional_stock_props{$_} = 1;
94 if (%additional_stock_props){
95 %stock_props = (%stock_props, %additional_stock_props);
99 my %stockprops_values;
100 if ($accession_numbers_arrayref && scalar(@$accession_numbers_arrayref)>0){
101 $stockprops_values{'accession number'} = {
102 matchtype => 'one of',
103 value => join(',', @$accession_numbers_arrayref)
106 if ($germplasm_puis_arrayref && scalar(@$germplasm_puis_arrayref)>0){
107 foreach (@$germplasm_puis_arrayref) {
108 $stockprops_values{'PUI'} = {
109 matchtype => 'contains',
110 value => $_
114 if ($synonyms_arrayref && scalar(@$synonyms_arrayref)>0){
115 foreach (@$synonyms_arrayref) {
116 $stockprops_values{'stock_synonym'} = {
117 matchtype => 'contains',
118 value => $_
123 my $references = CXGN::BrAPI::v2::ExternalReferences->new({
124 bcs_schema => $self->bcs_schema,
125 table_name => 'stock',
126 table_id_key => 'stock_id',
127 id => $germplasm_ids_arrayref
129 my $reference_result = $references->search();
132 my $stock_search = CXGN::Stock::Search->new({
133 bcs_schema=>$self->bcs_schema,
134 people_schema=>$self->people_schema,
135 phenome_schema=>$self->phenome_schema,
136 match_type=>$match_type,
137 uniquename_list=>$germplasm_names_arrayref,
138 genus_list=>$genera_arrayref,
139 species_list=>$species_arrayref,
140 crop_name_list=>$crop_names_arrayref,
141 stock_id_list=>$germplasm_ids_arrayref,
142 stock_type_id=>$accession_type_cvterm_id,
143 stockprops_values=>\%stockprops_values,
144 stockprop_columns_view=>\%stock_props,
145 trial_id_list=>$study_db_id,
146 trial_name_list=>$study_names,
147 external_ref_id_list=>$external_reference_id_arrayref,
148 external_ref_source_list=>$external_reference_source_arrayref,
149 limit=>$limit,
150 offset=>$offset,
151 display_pedigree=>1
153 my ($result, $total_count) = $stock_search->search();
155 my $main_production_site_url = SGN::Context->new()->get_conf('main_production_site_url');
157 my @data;
158 foreach (@$result){
159 # my @type_of_germplasm_storage_codes = $_->{'type of germplasm storage code'} ? split ',', $_->{'type of germplasm storage code'} : ();
160 my @type_of_germplasm_storage_codes;
161 if($_->{'type of germplasm storage code'}){
162 my @items = split ',', $_->{'type of germplasm storage code'};
163 foreach(@items){
164 push @type_of_germplasm_storage_codes ,{
165 code=>$_,
166 description=>undef
170 my @donors = {
171 donorAccessionNumber=>$_->{'donor'} ne '' ? $_->{'donor'} : undef ,
172 donorInstituteCode=>$_->{'donor institute'} ne '' ? $_->{'donor institute'} : undef ,
174 my @synonyms;
175 if($_->{synonyms}){
176 foreach(@{ $_->{synonyms} }){
177 push @synonyms, {
178 synonym=>$_,
179 type=>undef
183 my @ncbi_taxon_ids = split ',', $_->{'ncbi_taxonomy_id'};
184 my @taxons;
185 foreach (@ncbi_taxon_ids){
186 push @taxons, {
187 sourceName => 'NCBI',
188 taxonId => $_
192 #Get external references and check for search params
193 my @references;
194 if (%$reference_result{$_->{stock_id}}){
195 foreach (@{%$reference_result{$_->{stock_id}}}){
197 push @references, $_;
201 my $female_parent_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'female_parent', 'stock_relationship')->cvterm_id();
202 my $q = "SELECT value FROM stock_relationship WHERE object_id = ? AND type_id = ?;";
203 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
204 $h->execute($_->{stock_id}, $female_parent_cvterm_id);
205 my ($cross_type) = $h->fetchrow_array();
206 if ( ! defined $cross_type) {
207 $cross_type = "unknown";
210 #getting additional info
211 my $additional_info;
212 my %additional;
213 foreach my $prop (keys %additional_stock_props){
214 if($_->{$prop}){
215 $additional{$prop} = $_->{$prop};
219 if (defined $_->{'stock_additional_info'} && $_->{'stock_additional_info'} ne '' && %additional) {
220 $additional_info = decode_json($_->{'stock_additional_info'});
221 $additional_info = {%$additional_info , ("additionalProps" => \%additional)} ;
222 } elsif (defined $_->{'stock_additional_info'} && $_->{'stock_additional_info'} ne '') {
223 $additional_info = decode_json($_->{'stock_additional_info'});
224 } elsif (%additional) {
225 $additional_info = {"additionalProps" => \%additional};
228 #Populating data
229 push @data, {
230 accessionNumber=>$_->{'accession number'},
231 acquisitionDate=>$_->{'acquisition date'} eq '' ? undef : $_->{'acquisition date'},
232 additionalInfo=>$additional_info,
233 biologicalStatusOfAccessionCode=>$_->{'biological status of accession code'} || 0,
234 biologicalStatusOfAccessionDescription=>undef,
235 breedingMethodDbId=>$cross_type,
236 collection=>undef,
237 commonCropName=>$_->{common_name},
238 countryOfOriginCode=>$_->{'country of origin'},
239 defaultDisplayName=>$_->{stock_name},
240 documentationURL=>$_->{'PUI'} && $_->{'PUI'} ne '' ? $_->{'PUI'} : $main_production_site_url . "/stock/$_->{stock_id}/view",
241 donors=>\@donors,
242 externalReferences=>\@references,
243 genus=>$_->{genus},
244 germplasmName=>$_->{uniquename},
245 germplasmOrigin=>[],
246 germplasmDbId=>qq|$_->{stock_id}|,
247 germplasmPUI=>$_->{'PUI'} || $main_production_site_url . "/stock/$_->{stock_id}/view",
248 germplasmPreprocessing=>undef,
249 instituteCode=>$_->{'institute code'},
250 instituteName=>$_->{'institute name'},
251 pedigree=>$_->{pedigree},
252 seedSource=>$_->{'seed source'},
253 seedSourceDescription=>$_->{'seed source'},
254 species=>$_->{species},
255 speciesAuthority=>$_->{speciesAuthority},
256 storageTypes=>\@type_of_germplasm_storage_codes,
257 subtaxa=>$_->{subtaxa},
258 subtaxaAuthority=>$_->{subtaxaAuthority},
259 synonyms=> \@synonyms,
260 taxonIds=>\@taxons,
264 my %result = (data => \@data);
265 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
266 return CXGN::BrAPI::JSONResponse->return_success(\%result, $pagination, \@data_files, $status, 'Germplasm result constructed');
269 sub germplasm_detail {
270 my $self = shift;
271 my $stock_id = shift;
272 my $c = shift;
274 my $status = $self->status;
275 my $page_size = $self->page_size;
276 my $page = $self->page;
277 my @data_files;
278 my $verify_id = $self->bcs_schema->resultset('Stock::Stock')->find({stock_id=>$stock_id});
279 if (!$verify_id) {
280 return CXGN::BrAPI::JSONResponse->return_error($status, 'GermplasmDbId does not exist in the database');
283 my @result = _simple_search($self,[$stock_id],undef,$c);
284 my $total_count = scalar(@result);
286 print STDERR "germ detail: " . Dumper @result ."\n";
288 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
289 return CXGN::BrAPI::JSONResponse->return_success(@result, $pagination, \@data_files, $status, 'Germplasm detail result constructed');
292 sub germplasm_pedigree {
293 my $self = shift;
294 my $inputs = shift;
295 my $stock_id = $inputs->{stock_id};
296 my $status = $self->status;
298 my $direct_descendant_ids;
299 my %result;
300 my $total_count = 0;
301 my @data_files;
303 push @$direct_descendant_ids, $stock_id; #excluded in parent retrieval to prevent loops
305 my $stock = $self->bcs_schema->resultset("Stock::Stock")->find({stock_id => $stock_id});
307 if ($stock) {
308 $total_count = 1;
309 my $stock_uniquename = $stock->uniquename();
310 my $stock_type = $stock->type_id();
312 my $mother;
313 my $father;
315 ## Get parents relationships
316 my $cvterm_female_parent = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'female_parent', 'stock_relationship')->cvterm_id();
317 my $cvterm_male_parent = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'male_parent', 'stock_relationship')->cvterm_id();
319 my $cvterm_rootstock_of = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'rootstock_of', 'stock_relationship')->cvterm_id();
320 my $cvterm_scion_of = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'scion_of', 'stock_relationship')->cvterm_id();
322 my $accession_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
324 #get the stock relationships for the stock
325 my $female_parent_stock_id;
326 my $male_parent_stock_id;
328 my $stock_relationships = $stock->search_related("stock_relationship_objects",undef,{ prefetch => ['type','subject'] });
330 my $female_parent_relationship = $stock_relationships->find({type_id => { in => [ $cvterm_female_parent, $cvterm_scion_of ]}, subject_id => {'not_in' => $direct_descendant_ids}});
331 if ($female_parent_relationship) {
332 $female_parent_stock_id = $female_parent_relationship->subject_id();
333 $mother = $self->bcs_schema->resultset("Stock::Stock")->find({stock_id => $female_parent_stock_id})->uniquename();
335 my $male_parent_relationship = $stock_relationships->find({type_id => { in => [ $cvterm_male_parent, $cvterm_rootstock_of ]}, subject_id => {'not_in' => $direct_descendant_ids}});
336 if ($male_parent_relationship) {
337 $male_parent_stock_id = $male_parent_relationship->subject_id();
338 $father = $self->bcs_schema->resultset("Stock::Stock")->find({stock_id => $male_parent_stock_id})->uniquename();
341 ##Get sibblings
342 my $q = "SELECT DISTINCT female_parent.stock_id, female_parent.uniquename, male_parent.stock_id, male_parent.uniquename, progeny.stock_id, progeny.uniquename, stock_relationship1.value
343 FROM stock_relationship as stock_relationship1
344 INNER JOIN stock AS female_parent ON (stock_relationship1.subject_id = female_parent.stock_id) AND stock_relationship1.type_id = ?
345 INNER JOIN stock AS progeny ON (stock_relationship1.object_id = progeny.stock_id) AND progeny.type_id = ?
346 LEFT JOIN stock_relationship AS stock_relationship2 ON (progeny.stock_id = stock_relationship2.object_id) AND stock_relationship2.type_id = ?
347 LEFT JOIN stock AS male_parent ON (stock_relationship2.subject_id = male_parent.stock_id) ";
349 my $h;
351 if($female_parent_stock_id && $male_parent_stock_id){
352 $q = $q . "WHERE female_parent.stock_id = ? AND male_parent.stock_id = ?";
353 $h = $self->bcs_schema()->storage->dbh()->prepare($q);
354 $h->execute($cvterm_female_parent, $accession_cvterm, $cvterm_male_parent, $female_parent_stock_id, $male_parent_stock_id);
356 elsif ($female_parent_stock_id) {
357 $q = $q . "WHERE female_parent.stock_id = ? ORDER BY male_parent.stock_id";
358 $h = $self->bcs_schema()->storage->dbh()->prepare($q);
359 $h->execute($cvterm_female_parent, $accession_cvterm, $cvterm_male_parent, $female_parent_stock_id);
361 elsif ($male_parent_stock_id) {
362 $q = $q . "WHERE male_parent.stock_id = ? ORDER BY female_parent.stock_id";
363 $h = $self->bcs_schema()->storage->dbh()->prepare($q);
364 $h->execute($cvterm_female_parent, $accession_cvterm, $cvterm_male_parent, $male_parent_stock_id);
366 else {
367 $h = $self->bcs_schema()->storage->dbh()->prepare($q);
368 $h->execute($cvterm_female_parent, $accession_cvterm, $cvterm_male_parent);
371 my @siblings = ();
372 my $cross_plan;
374 while (my($female_parent_id, $female_parent_name, $male_parent_id, $male_parent_name, $progeny_id, $progeny_name, $cross_type) = $h->fetchrow_array()){
375 if ($progeny_id ne $stock_id){
376 push @siblings, {
377 germplasmDbId => qq|$progeny_id|,
378 germplasmName => $progeny_name
381 $cross_plan = $cross_type;
384 #Cross information
385 my @membership_info = ();
386 my $cross_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross', 'stock_type')->cvterm_id();
388 if ($stock_type eq $cross_cvterm){
390 my $cross_member_of_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "cross_member_of", "stock_relationship")->cvterm_id();
391 my $cross_experiment_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'cross_experiment', 'experiment_type')->cvterm_id();
392 my $family_name_type_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, "family_name", "stock_type")->cvterm_id();
393 my $project_year_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'project year', 'project_property')->cvterm_id();
395 my $q = "SELECT project.project_id, project.name, project.description, stock.stock_id, stock.uniquename, year.value
396 FROM nd_experiment_stock
397 JOIN nd_experiment ON (nd_experiment_stock.nd_experiment_id = nd_experiment.nd_experiment_id) AND nd_experiment.type_id = ?
398 JOIN nd_experiment_project ON (nd_experiment_project.nd_experiment_id = nd_experiment.nd_experiment_id)
399 JOIN project ON (nd_experiment_project.project_id = project.project_id)
400 LEFT JOIN projectprop AS year ON (project.project_id=year.project_id)
401 LEFT JOIN stock_relationship ON (nd_experiment_stock.stock_id = stock_relationship.subject_id) AND stock_relationship.type_id = ?
402 LEFT JOIN stock ON (stock_relationship.object_id = stock.stock_id) AND stock.type_id = ?
403 WHERE nd_experiment_stock.stock_id = ? AND year.type_id = ?";
405 my $h = $self->bcs_schema->storage->dbh()->prepare($q);
406 $h->execute($cross_experiment_type_id, $cross_member_of_type_id, $family_name_type_id, $stock_id, $project_year_cvterm_id);
409 while (my ($crossing_experiment_id, $crossing_experiment_name, $description, $family_id, $family_name, $year) = $h->fetchrow_array()){
410 push @membership_info, [$crossing_experiment_id, $crossing_experiment_name, $description, $family_id, $family_name, $year]
414 #Add parents:
415 my $parent = [];
416 if ($female_parent_stock_id){
417 push @$parent, {
418 germplasmDbId=>$female_parent_stock_id ? qq|$female_parent_stock_id| : $female_parent_stock_id ,
419 germplasmName=>$mother,
420 parentType=>'FEMALE',
423 if ($male_parent_stock_id){
424 push @$parent, {
425 germplasmDbId=>$male_parent_stock_id ? qq|$male_parent_stock_id| : $male_parent_stock_id,
426 germplasmName=>$father,
427 parentType=>'MALE',
432 %result = (
433 crossingProjectDbId=>$membership_info[0][0],
434 crossingYear=>$membership_info[0][5],
435 familyCode=>$membership_info[0][4],
436 germplasmDbId=>qq|$stock_id|,
437 germplasmName=>$stock_uniquename,
438 parents=>$parent,
439 pedigree=>"$mother/$father",
440 siblings=>\@siblings
444 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,1,0);
445 return CXGN::BrAPI::JSONResponse->return_success(\%result, $pagination, \@data_files, $status, 'Germplasm pedigree result constructed');
448 sub germplasm_progeny {
449 my $self = shift;
450 my $inputs = shift;
451 my $stock_id = $inputs->{stock_id};
452 my $status = $self->status;
453 my $mother_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'female_parent', 'stock_relationship')->cvterm_id();
454 my $father_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'male_parent', 'stock_relationship')->cvterm_id();
455 my $accession_cvterm = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
457 my $stock = $self->bcs_schema()->resultset("Stock::Stock")->find({
458 'type_id'=> $accession_cvterm,
459 'stock_id'=> $stock_id,
461 my $edges = $self->bcs_schema()->resultset("Stock::StockRelationship")->search(
464 'me.subject_id' => $stock_id,
465 'me.type_id' => $father_cvterm,
466 'object.type_id'=> $accession_cvterm
469 'me.subject_id' => $stock_id,
470 'me.type_id' => $mother_cvterm,
471 'object.type_id'=> $accession_cvterm
475 join => 'object',
476 '+select' => ['object.uniquename'],
477 '+as' => ['progeny_uniquename']
480 my $full_data = [];
481 while (my $edge = $edges->next) {
482 if ($edge->type_id==$mother_cvterm){
483 push @{$full_data}, {
484 germplasmDbId => "". $edge->object_id,
485 germplasmName => $edge->get_column('progeny_uniquename'),
486 parentType => "FEMALE"
488 } else {
489 push @{$full_data}, {
490 germplasmDbId => "". $edge->object_id,
491 germplasmName => $edge->get_column('progeny_uniquename'),
492 parentType => "MALE"
496 my $total_count = scalar @{$full_data};
497 my $page_size = 10;
498 if ($total_count > $page_size){
499 $page_size = $total_count;
501 my $page = 0;
502 my $result = {
503 germplasmName=>$stock->uniquename,
504 germplasmDbId=>$stock_id,
505 progeny=>[@{$full_data}],
507 my @data_files;
508 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
509 return CXGN::BrAPI::JSONResponse->return_success($result, $pagination, \@data_files, $status, 'Germplasm progeny result constructed');
512 sub germplasm_mcpd {
513 my $self = shift;
514 my $stock_id = shift;
516 my $status = $self->status;
517 my $page_size = $self->page_size;
518 my $page = $self->page;
520 my $schema = $self->bcs_schema();
521 my $accession_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
523 my $stock_search = CXGN::Stock::Search->new({
524 bcs_schema=>$self->bcs_schema,
525 people_schema=>$self->people_schema,
526 phenome_schema=>$self->phenome_schema,
527 match_type=>'exactly',
528 stock_id_list=>[$stock_id],
529 stock_type_id=>$accession_type_cvterm_id,
530 stockprop_columns_view=>{'accession number'=>1, 'PUI'=>1, 'seed source'=>1, 'institute code'=>1, 'institute name'=>1, 'biological status of accession code'=>1, 'country of origin'=>1, 'type of germplasm storage code'=>1, 'acquisition date'=>1, 'ncbi_taxonomy_id'=>1},
531 display_pedigree=>1
534 my ($result, $total_count) = $stock_search->search();
536 my %result;
538 foreach (@$result){
539 my $donors = $_->{donors};
540 my @donors;
541 foreach(@$donors){
542 push @donors, {
543 donorAccessionNumber=>$_->{donorAccessionNumber},
544 donorInstitute=>{
545 instituteCode=>$_->{donorInstituteCode},
546 instituteName=>undef,
548 donorAccessionPui=>$_->{germplasmPUI}
552 my @type_of_germplasm_storage_codes;
553 if($_->{'type of germplasm storage code'}){
554 my @items = split ',', $_->{'type of germplasm storage code'};
555 foreach(@items){
556 push @type_of_germplasm_storage_codes, $_;
559 my @names;
560 if($_->{uniquename}){
561 push @names, $_->{uniquename};
563 if($_->{synonyms}){
564 foreach(@{ $_->{synonyms} }){
565 push @names, $_;
568 if($_->{stock_name}){
569 push @names, $_->{stock_name};
572 my @ids;
573 if($_->{stock_id}){
574 push @ids, $_->{stock_id};
576 if($_->{'PUI'}){
577 push @ids, $_->{'PUI'};
579 if($_->{ncbi_taxonomy_id}){
580 push @ids, $_->{ncbi_taxonomy_id};
583 %result = (
584 accessionNames=>\@names,
585 alternateIDs=>\@ids,
586 breedingInstitutes=>{
587 instituteCode=>$_->{'institute code'},
588 instituteName=>$_->{'institute name'},
590 collectingInfo=>{},
591 mlsStatus=> undef,
592 remarks=>undef,
593 safetyDuplicateInstitutes=>undef,
594 germplasmDbId=>qq|$_->{stock_id}|,
595 accessionNumber=>$_->{'accession number'},
596 germplasmPUI=>$_->{'PUI'},
597 ancestralData=>$_->{pedigree},
598 commonCropName=>$_->{common_name},
599 instituteCode=>$_->{'institute code'},
600 biologicalStatusOfAccessionCode=>qq|$_->{'biological status of accession code'}| || "0",
601 countryOfOrigin=>$_->{'country of origin'},
602 storageTypeCodes=>\@type_of_germplasm_storage_codes,
603 genus=>$_->{genus},
604 species=>$_->{species},
605 speciesAuthority=>$_->{speciesAuthority},
606 subtaxon=>$_->{subtaxa},
607 subtaxonAuthority=>$_->{subtaxaAuthority},
608 donorInfo=>\@donors,
609 acquisitionDate=>$_->{'acquisition date'} eq '' ? undef : $_->{'acquisition date'}
612 my $total_count = (%result) ? 1 : 0;
613 my @data_files;
615 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
616 return CXGN::BrAPI::JSONResponse->return_success(\%result, $pagination, \@data_files, $status, 'Germplasm detail result constructed');
620 sub store {
621 my $self = shift;
622 my $data = shift;
623 my $user_id = shift;
624 my $c = shift;
626 if (!$user_id){
627 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('You must be logged in to add a seedlot!'), 401);
630 my $page_size = $self->page_size;
631 my $page = $self->page;
632 my $status = $self->status;
634 my $schema = $self->bcs_schema;
635 my $dbh = $self->bcs_schema()->storage()->dbh();
636 my $person = CXGN::People::Person->new($dbh, $user_id);
637 my $user_name = $person->get_username;
639 my $main_production_site_url = $c->config->{main_production_site_url};
641 my $accession_list;
642 my $organism_list;
643 my $pedigree_parents;
644 my $default_species = $c->config->{preferred_species};
646 foreach (@$data){
647 my $accession = $_->{germplasmName} || undef;
648 my $organism = $_->{species} || $default_species;
649 my $pedigree = $_->{pedigree} || undef;
650 push @$accession_list, $accession;
651 push @$organism_list, $organism;
652 my $pedigree_array = _process_pedigree_string($pedigree);
653 if (defined $pedigree_array) {
654 push @$pedigree_parents, @$pedigree_array;
658 #validate accessions
659 my $search_accession_list;
660 push @$search_accession_list, @$accession_list;
661 if (defined $pedigree_parents) {
662 push @$search_accession_list, @$pedigree_parents;
664 my %accessions_missing_hash = _get_nonexisting_accessions($self, $search_accession_list);
666 # Check if new germplasm already exist
667 my $existing_accessions = '';
668 foreach (@$accession_list){
669 if (!exists($accessions_missing_hash{$_})){
670 $existing_accessions = $existing_accessions . $_ ."," ;
674 if (length($existing_accessions) >0){
675 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('Existing germplasm in the database: %s', $existing_accessions), 409);
678 # Check if pedigree parents don't exist
679 my $missing_parents = '';
680 foreach (@$pedigree_parents){
681 if (length($_) > 0 && exists($accessions_missing_hash{$_})){
682 $missing_parents = $missing_parents . $_ ."," ;
686 if (length($missing_parents) >0){
687 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('Missing parent accessions: %s', $missing_parents), 404);
690 #validate organism
691 my $organism_search = CXGN::BreedersToolbox::OrganismFuzzySearch->new({schema => $schema});
692 my $organism_result = $organism_search->get_matches($organism_list, '1');
694 my @allowed_organisms;
695 my $missing_organisms = '';
696 my $found = $organism_result->{found};
698 foreach (@$found){
699 push @allowed_organisms, $_->{unique_name};
701 my %allowed_organisms = map {$_=>1} @allowed_organisms;
703 foreach (@$organism_list){
704 if (!exists($allowed_organisms{$_})){
705 $missing_organisms = $missing_organisms . $_ . ",";
708 if (length($missing_organisms) >0){
709 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('Organisms were not found on the database: %s', $missing_organisms), 404);
712 my $type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'accession', 'stock_type')->cvterm_id();
714 my @added_stocks;
715 my $coderef_bcs = sub {
716 foreach my $params (@$data){
717 my $species = $params->{species} || $default_species;
718 my $uniquename = $params->{germplasmName} || undef;
719 my $name = $params->{defaultDisplayName} || $uniquename;
720 my $accessionNumber = $params->{accessionNumber} || undef;
721 my $germplasmPUI = $params->{germplasmPUI} || undef;
722 my $germplasmSeedSource = $params->{seedSource} || undef;
723 my $instituteCode = $params->{instituteCode} || undef;
724 my $instituteName = $params->{instituteName} || undef;
725 my $biologicalStatusOfAccessionCode = $params->{biologicalStatusOfAccessionCode} || undef;
726 my $countryOfOriginCode = $params->{countryOfOriginCode} || undef;
727 my $typeOfGermplasmStorageCode = $params->{storageTypes}->[0]->{code} || undef;
728 my $donors = $params->{donors} || undef;
729 my $acquisitionDate = $params->{acquisitionDate} || undef;
730 my $externalReferences = $params->{externalReferences} || undef;
731 #adding breedbase specific info using additionalInfo
732 my $population_name = $params->{collection} || undef;
733 my $organization_name = $params->{additionalInfo}->{organizationName} || undef;
734 my $transgenic = $params->{additionalInfo}->{transgenic} || undef;
735 my $notes = $params->{additionalInfo}->{notes} || undef;
736 my $state = $params->{additionalInfo}->{state} || undef;
737 my $variety = $params->{additionalInfo}->{variety} || undef;
738 my $locationCode = $params->{additionalInfo}->{locationCode} || undef;
739 my $description = $params->{additionalInfo}->{description} || undef;
740 my $stock_id = $params->{additionalInfo}->{stock_id} || undef;
741 # Get misc additionalInfo and remove specific codes above
742 my %specific_keys = map { $_ => 1 } ("organizationName", "transgenic", "notes", "state", "variety", "locationCode", "description", "stock_id");
743 my $raw_additional_info = $params->{additionalInfo} || undef;
744 my %additional_info;
745 if (defined $raw_additional_info) {
746 foreach my $key (keys %$raw_additional_info) {
747 if (!exists($specific_keys{$key})) {
748 $additional_info{$key} = $raw_additional_info->{$key};
752 my $pedigree = $params->{pedigree} || undef;
753 my $pedigree_array = _process_pedigree_string($pedigree);
754 my $mother = defined $pedigree_array && scalar(@$pedigree_array) > 0 && length(@$pedigree_array[0]) > 0 ? @$pedigree_array[0] : undef;
755 my $father = defined $pedigree_array && scalar(@$pedigree_array) > 1 ? @$pedigree_array[1] : undef;
756 my $synonyms = $params->{synonyms} || [];
757 my @synonymNames;
758 foreach(@$synonyms) {
759 if ($_->{synonym}) {
760 push @synonymNames, $_->{synonym};
763 #not supported
764 # speciesAuthority
765 # genus
766 # commonCropName
767 # biologicalStatusOfAccessionDescription
768 # germplasmSeedSourceDescription
769 # breedingMethodDbId
770 # documentationURL
771 # germplasmOrigin
772 # germplasmPreprocessing
773 # taxonIds
774 # subtaxa
775 # subtaxaAuthority
777 if (exists($allowed_organisms{$species})){
778 my $stock = CXGN::Stock::Accession->new({
779 schema => $schema,
780 check_name_exists => 0,
781 main_production_site_url => $main_production_site_url,
782 type => 'accession',
783 type_id => $type_id,
784 species => $species,
785 name => $name,
786 uniquename => $uniquename,
787 organization_name => $organization_name,
788 population_name => $population_name,
789 description => $description,
790 accessionNumber => $accessionNumber,
791 germplasmPUI => $germplasmPUI,
792 germplasmSeedSource => $germplasmSeedSource,
793 synonyms => \@synonymNames,
794 instituteCode => $instituteCode,
795 instituteName => $instituteName,
796 biologicalStatusOfAccessionCode => $biologicalStatusOfAccessionCode,
797 countryOfOriginCode => $countryOfOriginCode,
798 typeOfGermplasmStorageCode => $typeOfGermplasmStorageCode,
799 donors => $donors,
800 acquisitionDate => $acquisitionDate eq '' ? undef : $acquisitionDate,
801 transgenic => $transgenic,
802 notes => $notes,
803 state => $state,
804 variety => $variety,
805 locationCode => $locationCode,
806 sp_person_id => $user_id,
807 user_name => $user_name,
808 modification_note => 'Bulk load of accession information',
809 mother_accession => $mother,
810 father_accession => $father,
811 additional_info => \%additional_info
813 my $added_stock_id = $stock->store();
814 push @added_stocks, $added_stock_id;
816 if ($externalReferences && scalar $externalReferences > 0) {
817 my $references = CXGN::BrAPI::v2::ExternalReferences->new({
818 bcs_schema => $self->bcs_schema,
819 table_name => 'stock',
820 table_id_key => 'stock_id',
821 external_references => $externalReferences,
822 id => $added_stock_id
824 my $reference_result = $references->store();
830 #save data
831 my $transaction_error;
833 try {
834 $schema->txn_do($coderef_bcs);
836 catch {
837 $transaction_error = $_;
840 if ($transaction_error){
841 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('There was an error storing germplasm %s', $transaction_error));
844 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
846 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath}, 0);
848 #retrieve saved items
849 my @data = _simple_search($self,undef,$accession_list);
850 my $total_count = scalar(@data);
852 my @data_files;
853 my %result = (data => \@data);
854 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
855 return CXGN::BrAPI::JSONResponse->return_success(\%result, $pagination, \@data_files, $status, 'Germplasm saved');
859 sub update {
860 my $self = shift;
861 my $germplasm_id = shift;
862 my $data = shift;
863 my $user_id = shift;
864 my $c = shift;
866 my $default_species = $c->config->{preferred_species};
868 if (!$user_id){
869 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('You must be logged in to add a seedlot!'));
872 my $page_size = $self->page_size;
873 my $page = $self->page;
874 my $status = $self->status;
876 my $schema = $self->bcs_schema;
877 my $dbh = $self->bcs_schema()->storage()->dbh();
878 my $person = CXGN::People::Person->new($dbh, $user_id);
879 my $user_name = $person->get_username;
881 my $stock_exists = $schema->resultset('Stock::Stock')->find({stock_id=>$germplasm_id});
882 if (!$stock_exists) {
883 return CXGN::BrAPI::JSONResponse->return_error($status, 'GermplasmDbId does not exist in the database',400);
886 my $main_production_site_url = $c->config->{main_production_site_url};
888 #validate organism
889 my $organism_list;
891 foreach (@$data){
892 my $organism = $_->{species} || $default_species;
893 push @$organism_list, $organism;
896 my $organism_search = CXGN::BreedersToolbox::OrganismFuzzySearch->new({schema => $schema});
897 my $organism_result = $organism_search->get_matches($organism_list, '1');
899 my @allowed_organisms;
900 my $missing_organisms = '';
901 my $found = $organism_result->{found};
903 foreach (@$found){
904 push @allowed_organisms, $_->{unique_name};
906 my %allowed_organisms = map {$_=>1} @allowed_organisms;
908 foreach (@$organism_list){
909 if (!exists($allowed_organisms{$_})){
910 $missing_organisms = $missing_organisms . $_ . ",";
913 if (length($missing_organisms) >0){
914 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('Organisms were not found on the database: %s', $missing_organisms));
917 my $type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'accession', 'stock_type')->cvterm_id();
919 #sub rutine to save data
920 my @added_stocks;
921 my $coderef_bcs = sub {
922 foreach my $params (@$data){
923 my $species = $params->{species} || $default_species;
924 my $uniquename = $params->{germplasmName} || undef;
925 my $name = $params->{defaultDisplayName} || $uniquename;
926 my $accessionNumber = $params->{accessionNumber} || undef;
927 my $germplasmPUI = $params->{germplasmPUI} || undef;
928 my $germplasmSeedSource = $params->{seedSource} || undef;
929 my $instituteCode = $params->{instituteCode} || undef;
930 my $instituteName = $params->{instituteName} || undef;
931 my $biologicalStatusOfAccessionCode = $params->{biologicalStatusOfAccessionCode} || undef;
932 my $countryOfOriginCode = $params->{countryOfOriginCode} || undef;
933 my $typeOfGermplasmStorageCode = $params->{storageTypes}->[0]->{code} || undef;
934 my $donors = $params->{donors} || undef;
935 my $acquisitionDate = $params->{acquisitionDate} || undef;
936 my $externalReferences = $params->{externalReferences} || undef;
937 #adding breedbase specific info using additionalInfo
938 my $population_name = $params->{collection} || undef;
939 my $organization_name = $params->{additionalInfo}->{organizationName} || undef;
940 my $transgenic = $params->{additionalInfo}->{transgenic} || undef;
941 my $notes = $params->{additionalInfo}->{notes} || undef;
942 my $state = $params->{additionalInfo}->{state} || undef;
943 my $variety = $params->{additionalInfo}->{variety} || undef;
944 my $locationCode = $params->{additionalInfo}->{locationCode} || undef;
945 my $description = $params->{additionalInfo}->{description} || undef;
946 my $stock_id = $params->{additionalInfo}->{stock_id} || undef;
947 # Get misc additionalInfo and remove specific codes above
948 my %specific_keys = map { $_ => 1 } ("organizationName", "transgenic", "notes", "state", "variety", "locationCode", "description", "stock_id");
949 my $raw_additional_info = $params->{additionalInfo} || undef;
950 my %additional_info;
951 if (defined $raw_additional_info) {
952 foreach my $key (keys %$raw_additional_info) {
953 if (!exists($specific_keys{$key})) {
954 $additional_info{$key} = $raw_additional_info->{$key};
958 my $pedigree = $params->{pedigree} || undef;
959 my $pedigree_array = _process_pedigree_string($pedigree);
960 my $mother = defined $pedigree_array && scalar(@$pedigree_array) > 0 ? @$pedigree_array[0] : undef;
961 my $father = defined $pedigree_array && scalar(@$pedigree_array) > 1 ? @$pedigree_array[1] : undef;
962 my $synonyms = $params->{synonyms} || [];
963 my @synonymNames;
964 foreach(@$synonyms) {
965 if ($_->{synonym}) {
966 push @synonymNames, $_->{synonym};
969 #not supported
970 # speciesAuthority
971 # genus
972 # commonCropName
973 # biologicalStatusOfAccessionDescription
974 # germplasmSeedSourceDescription
975 # breedingMethodDbId
976 # collection
977 # documentationURL
978 # germplasmOrigin
979 # germplasmPreprocessing
980 # taxonIds
981 # subtaxa
982 # subtaxaAuthority
983 # pedigree
985 if (exists($allowed_organisms{$species})){
986 my $stock = CXGN::Stock::Accession->new({
987 schema => $schema,
988 check_name_exists => 0,
989 main_production_site_url => $main_production_site_url,
990 type => 'accession',
991 type_id => $type_id,
992 species => $species,
993 stock_id => $germplasm_id,
994 name => $name,
995 uniquename => $uniquename,
996 organization_name => $organization_name,
997 population_name => $population_name,
998 description => $description,
999 accessionNumber => $accessionNumber,
1000 germplasmPUI => $germplasmPUI,
1001 germplasmSeedSource => $germplasmSeedSource,
1002 synonyms => \@synonymNames,
1003 instituteCode => $instituteCode,
1004 instituteName => $instituteName,
1005 biologicalStatusOfAccessionCode => $biologicalStatusOfAccessionCode,
1006 countryOfOriginCode => $countryOfOriginCode,
1007 typeOfGermplasmStorageCode => $typeOfGermplasmStorageCode,
1008 donors => $donors,
1009 acquisitionDate => $acquisitionDate eq '' ? undef : $acquisitionDate,
1010 transgenic => $transgenic,
1011 notes => $notes,
1012 state => $state,
1013 variety => $variety,
1014 locationCode => $locationCode,
1015 sp_person_id => $user_id,
1016 user_name => $user_name,
1017 modification_note => 'Bulk load of accession information',
1018 mother_accession => $mother,
1019 father_accession => $father,
1020 additional_info => \%additional_info
1022 my $added_stock_id = $stock->store();
1024 my $previous_name = $stock_exists->uniquename();
1026 if($previous_name ne $uniquename){
1027 $stock_exists->uniquename($uniquename);
1028 $stock_exists->update();
1031 push @added_stocks, $added_stock_id;
1033 my $references = CXGN::BrAPI::v2::ExternalReferences->new({
1034 bcs_schema => $self->bcs_schema,
1035 table_name => 'stock',
1036 table_id_key => 'stock_id',
1037 external_references => $externalReferences ? $externalReferences : [],
1038 id => $germplasm_id
1040 my $reference_result = $references->store();
1045 #update data
1046 my $transaction_error;
1048 try {
1049 $schema->txn_do($coderef_bcs);
1052 catch {
1053 $transaction_error = $_;
1056 if ($transaction_error){
1057 return CXGN::BrAPI::JSONResponse->return_error($self->status, sprintf('There was an error storing germplasm %s', $transaction_error));
1060 #update matviews
1061 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
1062 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop', 'concurrent', $c->config->{basepath}, 0);
1064 #retrieve updated item
1065 my @result = _simple_search($self,[$germplasm_id]);
1066 my @data_files;
1067 my $total_count = scalar(@result);
1068 my $pagination = CXGN::BrAPI::Pagination->pagination_response($total_count,$page_size,$page);
1069 return CXGN::BrAPI::JSONResponse->return_success(@result, $pagination, \@data_files, $status, 'Germplasm updated');
1072 sub _simple_search {
1073 my $self = shift;
1074 my $germplasm_ids_arrayref = shift;
1075 my $germplasm_names_arrayref = shift;
1076 my $c = shift;
1078 my $accession_type_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'accession', 'stock_type')->cvterm_id();
1080 my %stock_props = (
1081 'accession number'=>1,
1082 'acquisition date'=>1,
1083 'biological status of accession code'=>1,
1084 'country of origin'=>1,
1085 'donor'=>1,
1086 'donor institute'=>1,
1087 'institute code'=>1,
1088 'institute name'=>1,
1089 'ncbi_taxonomy_id'=>1,
1090 'PUI'=>1,
1091 'seed source'=>1,
1092 'stock_additional_info'=>1,
1093 'type of germplasm storage code'=>1 );
1095 ## Additional stock props for additional info.
1096 my %additional_stock_props;
1097 my @editable_stock_props = SGN::Context->new()->get_conf('editable_stock_props') ? split ',', SGN::Context->new()->get_conf('editable_stock_props'): undef;
1098 my %editable_stock_props = map { $_=>1 } @editable_stock_props;
1100 foreach (keys %editable_stock_props){
1101 if(!%stock_props{$_}){
1102 $additional_stock_props{$_} = 1;
1106 if (%additional_stock_props){
1107 %stock_props = (%stock_props, %additional_stock_props);
1110 ##Getting references
1111 my $references = CXGN::BrAPI::v2::ExternalReferences->new({
1112 bcs_schema => $self->bcs_schema,
1113 table_name => 'stock',
1114 table_id_key => 'stock_id',
1115 id => $germplasm_ids_arrayref
1117 my $reference_result = $references->search();
1119 my $stock_search = CXGN::Stock::Search->new({
1120 bcs_schema=>$self->bcs_schema,
1121 people_schema=>$self->people_schema,
1122 phenome_schema=>$self->phenome_schema,
1123 match_type=>'exactly',
1124 uniquename_list=>$germplasm_names_arrayref,
1125 stock_id_list=>$germplasm_ids_arrayref,
1126 stock_type_id=>$accession_type_cvterm_id,
1127 stockprop_columns_view=>\%stock_props,
1128 display_pedigree=>1
1130 my ($result, $total_count) = $stock_search->search();
1132 my $main_production_site_url = SGN::Context->new()->get_conf('main_production_site_url');
1134 my @data;
1135 foreach (@$result){
1136 # my @type_of_germplasm_storage_codes = $_->{'type of germplasm storage code'} ? split ',', $_->{'type of germplasm storage code'} : ();
1137 my @type_of_germplasm_storage_codes;
1138 if($_->{'type of germplasm storage code'}){
1139 my @items = split ',', $_->{'type of germplasm storage code'};
1140 foreach(@items){
1141 push @type_of_germplasm_storage_codes ,{
1142 code=>$_,
1143 description=>undef
1147 my @donors = {
1148 donorAccessionNumber=>$_->{donor} ne '' ? $_->{'donor'} : undef ,
1149 donorInstituteCode=>$_->{'donor institute'} ne '' ? $_->{'donor institute'} : undef ,
1151 my @synonyms;
1152 if($_->{synonyms} && scalar @{ $_->{synonyms} } > 0){
1153 foreach(@{ $_->{synonyms} }){
1154 print STDERR "pushing synonym: " . Dumper $_;
1155 push @synonyms, {
1156 synonym=>$_,
1157 type=>undef
1161 my @ncbi_taxon_ids = split ',', $_->{'ncbi_taxonomy_id'};
1162 my @taxons;
1163 foreach (@ncbi_taxon_ids){
1164 push @taxons, {
1165 sourceName => 'NCBI',
1166 taxonId => $_
1170 my @references;
1171 if (%$reference_result{$_->{stock_id}}){
1172 foreach (@{%$reference_result{$_->{stock_id}}}){
1173 push @references, $_;
1177 my $female_parent_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($self->bcs_schema, 'female_parent', 'stock_relationship')->cvterm_id();
1178 my $q = "SELECT value FROM stock_relationship WHERE object_id = ? AND type_id = ?;";
1179 my $h = $self->bcs_schema->storage()->dbh()->prepare($q);
1180 $h->execute($_->{stock_id}, $female_parent_cvterm_id);
1181 my ($cross_type) = $h->fetchrow_array();
1182 if ( ! defined $cross_type) {
1183 $cross_type = "unknown";
1186 my $additional_info;
1187 my %additional;
1188 foreach my $prop (keys %additional_stock_props){
1189 if($_->{$prop}){
1190 $additional{$prop} = $_->{$prop};
1194 if (defined $_->{'stock_additional_info'} && $_->{'stock_additional_info'} ne '' && %additional) {
1195 $additional_info = decode_json($_->{'stock_additional_info'});
1196 $additional_info = {%$additional_info , ("additionalProps" => \%additional)} ;
1197 } elsif (defined $_->{'stock_additional_info'} && $_->{'stock_additional_info'} ne '') {
1198 $additional_info = decode_json($_->{'stock_additional_info'});
1199 } elsif (%additional) {
1200 $additional_info = {"additionalProps" => \%additional};
1203 push @data, {
1204 accessionNumber=>$_->{'accession number'},
1205 acquisitionDate=>$_->{'acquisition date'} eq '' ? undef : $_->{'acquisition date'},
1206 additionalInfo=> $additional_info,
1207 biologicalStatusOfAccessionCode=>$_->{'biological status of accession code'} || 0,
1208 biologicalStatusOfAccessionDescription=>undef,
1209 breedingMethodDbId=>$cross_type,
1210 collection=>$_->{population_name},
1211 commonCropName=>$_->{common_name},
1212 countryOfOriginCode=>$_->{'country of origin'},
1213 defaultDisplayName=>$_->{stock_name},
1214 documentationURL=>$_->{'PUI'} && $_->{'PUI'} ne '' ? $_->{'PUI'} : $main_production_site_url . "/stock/$_->{stock_id}/view",
1215 donors=>\@donors,
1216 externalReferences=>\@references,
1217 genus=>$_->{genus},
1218 germplasmName=>$_->{uniquename},
1219 germplasmOrigin=>[],
1220 germplasmDbId=>qq|$_->{stock_id}|,
1221 germplasmPUI=>$_->{'PUI'} || $main_production_site_url . "/stock/$_->{stock_id}/view",
1222 germplasmPreprocessing=>undef,
1223 instituteCode=>$_->{'institute code'},
1224 instituteName=>$_->{'institute name'},
1225 pedigree=>$_->{pedigree},
1226 seedSource=>$_->{'seed source'},
1227 seedSourceDescription=>$_->{'seed source'},
1228 species=>$_->{species},
1229 speciesAuthority=>$_->{speciesAuthority},
1230 storageTypes=>\@type_of_germplasm_storage_codes,
1231 subtaxa=>$_->{subtaxa},
1232 subtaxaAuthority=>$_->{subtaxaAuthority},
1233 synonyms=> @synonyms ? \@synonyms : [],
1234 taxonIds=>\@taxons,
1237 return @data;
1240 sub _process_pedigree_string {
1241 my $pedigree = shift;
1243 my $pedigree_parents;
1245 if (defined $pedigree) {
1246 my @pedigree_array = split('/', $pedigree);
1247 if (scalar(@pedigree_array) > 0){
1248 my $mother = @pedigree_array[0];
1249 push @$pedigree_parents, $mother;
1250 if (scalar(@pedigree_array) > 1){
1251 my $father = @pedigree_array[1];
1252 push @$pedigree_parents, $father;
1257 return $pedigree_parents;
1260 sub _get_nonexisting_accessions {
1261 my $self = shift;
1262 my $accession_list = shift;
1264 my $schema = $self->bcs_schema;
1266 my $validator = CXGN::List::Validate->new();
1267 my @absent_accessions = @{$validator->validate($schema, 'accessions', $accession_list)->{'missing'}};
1268 my %accessions_missing_hash = map { $_ => 1 } @absent_accessions;
1270 return %accessions_missing_hash;