8 use CXGN
::BrAPI
::v2
::ExternalReferences
;
9 use CXGN
::BrAPI
::v2
::Methods
;
10 use CXGN
::BrAPI
::v2
::Scales
;
11 use CXGN
::BrAPI
::Exceptions
::ConflictException
;
12 use CXGN
::BrAPI
::Exceptions
::ServerException
;
14 ## to do: add concept of trait short name; provide alternate constructors for term, shortname, and synonyms etc.
16 has
'bcs_schema' => ( isa
=> 'Bio::Chado::Schema',
21 has
'cvterm_id' => (isa
=> 'Maybe[Int]',
26 has
'cvterm' => ( isa
=> 'Bio::Chado::Schema::Result::Cv::Cvterm',
30 has
'name' => ( isa
=> 'Str',
35 return $self->cvterm->name();
40 has
'display_name' => (isa
=> 'Str',
46 my $name = $self->name();
47 my $accession = $self->accession();
48 #print STDERR $db." ".$name." ".$accession."\n";
49 if ($db && $name && $accession ) {
50 return $name ."|".$db.":".$accession;
56 has
'accession' => (isa
=> 'Str',
61 my $rs = $self->bcs_schema()->resultset("Cv::Cvterm")
62 -> search
( { cvterm_id
=> $self->cvterm_id() })
63 -> search_related
("dbxref");
64 if ($rs->count() ==1) {
65 my $accession = $rs->first()->get_column("accession");
73 has
'term' => (isa
=> 'Str',
78 my $accession = $self->accession();
80 if ($accession && $db) {
81 return "$db:$accession";
87 has
'db' => ( isa
=> 'Str',
92 my $rs = $self->bcs_schema()->resultset("Cv::Cvterm")->search( { cvterm_id
=> $self->cvterm_id()})->search_related("dbxref")->search_related("db");
93 if ($rs->count() == 1) {
94 my $db_name = $rs->first()->get_column("name");
95 #print STDERR "DBNAME = $db_name\n";
110 my $rs = $self->cvterm->search_related("dbxref");
111 if ($rs->count() == 1) {
112 my $db_id = $rs->first()->get_column("db_id");
113 #print STDERR "DBID = $db_id\n";
128 my $rs = $self->cvterm->search_related("dbxref");
129 if ($rs->count() == 1) {
130 my $dbxref_id = $rs->first()->get_column("dbxref_id");
138 has
'definition' => (isa
=> 'Maybe[Str]',
143 return $self->cvterm->definition();
154 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
155 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_entity' },
160 return $row->value();
172 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
173 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_attribute' },
178 return $row->value();
184 has
'format' => (isa
=> 'Str',
190 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
192 cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_format'
198 return $row->value();
204 has
'default_value' => (
210 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
211 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_default_value' },
216 return $row->value();
228 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
229 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_minimum' },
234 return $row->value();
246 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
247 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_maximum' },
252 return $row->value();
258 has
'categories' => (
264 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
265 { cvterm_id
=> $self->cvterm_id(), 'type.name' => 'trait_categories' },
270 return $row->value();
276 has
'associated_plots' => ( isa
=> 'Str',
279 default => sub { "not yet implemented" }
282 has
'associated_accessions' => ( isa
=> 'Str',
285 default => sub { "not yet implemented" }
288 has
'uri' => (isa
=> 'Str',
293 my $row = $self->bcs_schema()->resultset("Cv::Cvtermprop")->find(
294 {cvterm_id
=> $self->cvterm_id(), 'type.name' => 'uri'},
299 return $row->value();
305 has
'ontology_id' => (
311 isa
=> 'Maybe[ArrayRef[Str]]',
316 my @synonyms = $self -> _fetch_synonyms
();
321 has
'external_references' => (
322 isa
=> 'Maybe[CXGN::BrAPI::v2::ExternalReferences]',
327 isa
=> 'Maybe[CXGN::BrAPI::v2::Methods]',
332 if (defined($self->cvterm_id)) {
333 return CXGN
::BrAPI
::v2
::Methods
->new({
334 bcs_schema
=> $self->bcs_schema,
335 cvterm_id
=> $self->cvterm_id
337 } else { return undef;}
342 isa
=> 'Maybe[CXGN::BrAPI::v2::Scales]',
347 if (defined($self->cvterm_id)) {
348 return CXGN
::BrAPI
::v2
::Scales
->new({
349 bcs_schema
=> $self->bcs_schema,
350 cvterm_id
=> $self->cvterm_id
352 } else {return undef;}
361 has
'additional_info' => (
363 isa
=> 'Maybe[HashRef]'
372 my $cv_id = $self->bcs_schema->resultset("Cv::Cv")->find(
374 name
=> 'trait_property'
377 )->get_column('cv_id');
382 has
'trait_entity_id' => (
388 my $trait_entity_id = $self->bcs_schema->resultset("Cv::Cvterm")->find(
390 name
=> 'trait_entity',
391 cv_id
=> $self->cv_id,
394 { key
=> 'cvterm_c1' }
395 )->get_column('cvterm_id');
396 return $trait_entity_id;
400 has
'trait_attribute_id' => (
406 my $trait_attribute_id = $self->bcs_schema->resultset("Cv::Cvterm")->find(
408 name
=> 'trait_attribute',
409 cv_id
=> $self->cv_id,
412 { key
=> 'cvterm_c1' }
413 )->get_column('cvterm_id');
414 return $trait_attribute_id;
419 #print STDERR "BUILDING...\n";
423 if ($self->cvterm_id){
424 # TODO: Throw a good error if cvterm can't be found
425 $cvterm = $self->bcs_schema()->resultset("Cv::Cvterm")->find( { cvterm_id
=> $self->cvterm_id });
426 $self->cvterm($cvterm);
427 $self->active($cvterm->is_obsolete == 0);
429 if (defined $cvterm) {
430 $self->name($self->name || $cvterm->name );
439 my $schema = $self->bcs_schema();
443 my $name = _trim
($self->name());
444 my $description = $self->definition();
445 my $ontology_id = $self->ontology_id(); # passed in value not used currently, uses config
446 my $synonyms = $self->synonyms();
447 my $active = $self->active();
448 my $additional_info = $self->additional_info();
449 my $trait_entity = $self->entity();
450 my $trait_attribute = $self->attribute();
453 # get cv_id from sgn_local.conf
454 my $context = SGN
::Context
->new;
455 my $cv_name = $context->get_conf('trait_ontology_cv_name');
456 my $cvterm_name = $context->get_conf('trait_ontology_cvterm_name');
457 my $ontology_name = $context->get_conf('trait_ontology_db_name');
459 # Get trait attributes cvterm ids
460 my $trait_entity_id = $self->trait_entity_id;
461 my $trait_attribute_id = $self->trait_attribute_id;
463 # get cv_id for cv_name
464 my $cv = $schema->resultset("Cv::Cv")->find(
470 my $cv_id = $cv->get_column('cv_id');
472 # get cvterm_id for cvterm_name
473 my $cvterm = $schema->resultset("Cv::Cvterm")->find(
475 name
=> $cvterm_name,
479 { key
=> 'cvterm_c1' }
482 my $root_id = $cvterm->get_column('cvterm_id');
484 # check to see if specified ontology exists
485 my $db = $schema->resultset("General::Db")->find(
487 name
=> $ontology_name
493 CXGN
::BrAPI
::Exceptions
::ServerException
->throw({message
=> "Error: Unable to create trait, ontology does not exist"});
496 $ontology_id = $db->get_column('db_id');
498 # check to see if cvterm name already exists and don't attempt if so
499 my $cvterm_exists = $schema->resultset("Cv::Cvterm")->find(
505 { key
=> 'cvterm_c1' }
508 if (defined($cvterm_exists)) {
509 CXGN
::BrAPI
::Exceptions
::ConflictException
->throw({message
=> "Variable with that name already exists"});
512 # lookup last numeric accession number in ontology if one exists so we can increment off that
513 my $q = "select accession from dbxref where db_id=".$ontology_id." and accession ~ ".q
('^\d+$')." order by accession desc limit 1;";
514 my $sth = $self->bcs_schema->storage->dbh->prepare($q);
516 my ($accession) = $sth->fetchrow_array();
518 if (!defined($accession)) {
519 $accession = '0000001';
524 # get cvterm_id for VARIABLE_OF
525 my $variable_of_cvterm = $schema->resultset("Cv::Cvterm")->find(
527 name
=> 'VARIABLE_OF',
531 { key
=> 'cvterm_c1' }
534 my $variable_of_id = $variable_of_cvterm->get_column('cvterm_id');
538 # setup transaction for rollbacks in case of error
541 # add trait info to dbxref
542 my $new_term_dbxref = $schema->resultset("General::Dbxref")->create(
543 { db_id
=> $ontology_id,
544 accession
=> $accession,
547 { key
=> 'dbxref_c1' },
550 # add trait info to cvterm
551 $new_term = $schema->resultset("Cv::Cvterm")->create(
554 definition
=> $description,
555 dbxref_id
=> $new_term_dbxref->dbxref_id(),
556 is_obsolete
=> $active ?
0 : 1
559 # set cvtermrelationship VARIABLE_OF to put terms under ontology
560 # add cvterm_relationship entry linking term to ontology root
561 my $relationship = $schema->resultset("Cv::CvtermRelationship")->create(
562 { type_id
=> $variable_of_id,
563 subject_id
=> $new_term->get_column('cvterm_id'),
564 object_id
=> $root_id
568 foreach my $synonym (@
{$synonyms}) {
569 $new_term->add_synonym($synonym);
574 my $prop_entity = $schema->resultset("Cv::Cvtermprop")->create(
576 cvterm_id
=> $new_term->get_column('cvterm_id'),
577 type_id
=> $trait_entity_id,
578 value
=> $trait_entity,
585 # Add trait attribute
586 if ($trait_attribute) {
587 my $prop_attribute = $schema->resultset("Cv::Cvtermprop")->create(
589 cvterm_id
=> $new_term->get_column('cvterm_id'),
590 type_id
=> $trait_attribute_id,
591 value
=> $trait_attribute,
597 # Save additional info
599 my $additional_info_type_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'cvterm_additional_info', 'trait_property')->cvterm_id();
600 if (defined $additional_info) {
601 my $prop_id = $schema->resultset("Cv::Cvtermprop")->create(
603 cvterm_id
=> $new_term->get_column('cvterm_id'),
604 type_id
=> $additional_info_type_id,
605 value
=> encode_json
$additional_info,
611 # save scale properties
612 $self->scale->{cvterm_id
} = $new_term->cvterm_id;
613 $self->scale->store();
614 $self->method->{cvterm_id
} = $new_term->cvterm_id;
615 $self->method->store();
616 if ($self->external_references) {
617 $self->external_references->{id
} = $new_term->cvterm_id;
618 my $result = $self->external_references->store();
619 $self->external_references->{id
} = [$new_term->cvterm_id];
624 $self->bcs_schema()->txn_do($coderef);
626 $self->cvterm_id($new_term->get_column('cvterm_id'));
627 $self->cvterm($new_term);
635 my $schema = $self->bcs_schema();
638 my $name = _trim
($self->name());
639 my $description = $self->definition();
640 my $entity = $self->entity();
641 my $attribute = $self->attribute();
642 my $active = $self->active();
643 my $synonyms = $self->synonyms();
644 my $cvterm_id = $self->cvterm_id();
645 my $additional_info = $self->additional_info();
647 my $trait_entity_id = $self->trait_entity_id();
648 my $trait_attribute_id = $self->trait_attribute_id();
650 $self->bcs_schema()->txn_do(sub {
652 # Update the variable
653 $self->cvterm->update({
655 definition
=> $description,
656 is_obsolete
=> $active ?
0 : 1
659 # Remove old synonyms
660 $self->delete_existing_synonyms();
663 foreach my $synonym (@
{$synonyms}) {
664 $self->cvterm->add_synonym($synonym);
667 # Update trait entity
668 $schema->resultset("Cv::Cvtermprop")->search(
670 cvterm_id
=> $self->cvterm_id,
671 type_id
=> $trait_entity_id
675 $schema->resultset("Cv::Cvtermprop")->create(
677 cvterm_id
=> $self->cvterm_id,
678 type_id
=> $trait_entity_id,
685 # Update trait attribute
686 $schema->resultset("Cv::Cvtermprop")->search(
688 cvterm_id
=> $self->cvterm_id,
689 type_id
=> $trait_attribute_id
693 $schema->resultset("Cv::Cvtermprop")->create(
695 cvterm_id
=> $self->cvterm_id,
696 type_id
=> $trait_attribute_id,
703 # Delete old additional info
704 my $additional_info_type_id = SGN
::Model
::Cvterm
->get_cvterm_row($schema, 'cvterm_additional_info', 'trait_property')->cvterm_id();
705 $schema->resultset("Cv::Cvtermprop")->search(
707 cvterm_id
=> $self->cvterm_id,
708 type_id
=> $additional_info_type_id
712 # Add new additional info
714 if (defined $additional_info) {
715 my $prop_id = $schema->resultset("Cv::Cvtermprop")->create(
717 cvterm_id
=> $self->cvterm_id,
718 type_id
=> $additional_info_type_id,
719 value
=> encode_json
$additional_info,
725 # update scale properties
726 $self->scale->{cvterm_id
} = $cvterm_id;
727 $self->scale->store();
728 $self->method->{cvterm_id
} = $cvterm_id;
729 $self->method->store();
730 if ($self->external_references) {
731 $self->external_references->{id
} = $cvterm_id;
732 $self->external_references->store();
733 $self->external_references->{id
} = [ $cvterm_id ];
738 #TODO: Query the variable
742 sub delete_existing_synonyms
{
744 my $schema = $self->bcs_schema();
745 $schema->resultset("Cv::Cvtermsynonym")->search(
746 {cvterm_id
=> $self->cvterm_id}
750 sub _fetch_synonyms
{
753 if (defined($self->cvterm)){
754 my $synonym_rs = $self->cvterm->cvtermsynonyms;
756 while ( my $s = $synonym_rs->next ) {
757 push @synonyms, $s->synonym;
760 my @sorted = sort { length $a <=> length $b } @synonyms;
764 # TODO: common utilities somewhere, used by Location also
765 sub _trim
{ #trim whitespace from both ends of a string
767 $s =~ s/^\s+|\s+$//g;
774 $id =~ s/.*\:(.*)$/$1/g;
778 sub get_active_string
{
780 return $self->{active
} ?
'active' : 'archived';