File Coverage

Bio/Ontology/SimpleOntologyEngine.pm
Criterion Covered Total %
statement 138 223 61.8
branch 52 94 55.3
condition 11 27 40.7
subroutine 27 39 69.2
pod 21 21 100.0
total 249 404 61.6


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Ontology::SimpleOntologyEngine
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Peter Dimitrov
7             #
8             # Copyright Peter Dimitrov
9             # (c) Peter Dimitrov, dimitrov@gnf.org, 2002.
10             # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2002.
11             #
12             # You may distribute this module under the same terms as perl itself.
13             # Refer to the Perl Artistic License (see the license accompanying this
14             # software package, or see http://www.perl.com/language/misc/Artistic.html)
15             # for the terms under which you may use, modify, and redistribute this module.
16             #
17             # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
18             # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19             # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20             #
21             # POD documentation - main docs before the code
22              
23             =head1 NAME
24              
25             Bio::Ontology::SimpleOntologyEngine - Implementation of OntologyEngineI interface
26              
27             =head1 SYNOPSIS
28              
29             my $soe = Bio::Ontology::SimpleOntologyEngine->new;
30              
31             =head1 DESCRIPTION
32              
33             This is a "simple" implementation of Bio::Ontology::OntologyEngineI.
34              
35             =head1 FEEDBACK
36              
37             =head2 Mailing Lists
38              
39             User feedback is an integral part of the evolution of this and other
40             Bioperl modules. Send your comments and suggestions preferably to
41             the Bioperl mailing list. Your participation is much appreciated.
42              
43             bioperl-l@bioperl.org - General discussion
44             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
45              
46             =head2 Support
47              
48             Please direct usage questions or support issues to the mailing list:
49              
50             I
51              
52             rather than to the module maintainer directly. Many experienced and
53             reponsive experts will be able look at the problem and quickly
54             address it. Please include a thorough description of the problem
55             with code and data examples if at all possible.
56              
57             =head2 Reporting Bugs
58              
59             Report bugs to the Bioperl bug tracking system to help us keep track
60             of the bugs and their resolution. Bug reports can be submitted via
61             the web:
62              
63             https://github.com/bioperl/bioperl-live/issues
64              
65             =head1 AUTHOR - Peter Dimitrov
66              
67             Email dimitrov@gnf.org
68              
69             =head1 CONTRIBUTORS
70              
71             Hilmar Lapp, hlapp at gmx.net
72              
73             =head1 APPENDIX
74              
75             The rest of the documentation details each of the object methods.
76             Internal methods are usually preceded with a _
77              
78             =cut
79              
80             # Let the code begin...
81              
82             package Bio::Ontology::SimpleOntologyEngine;
83 1     1   809 use strict;
  1         2  
  1         23  
84 1     1   4 use Carp;
  1         1  
  1         44  
85 1     1   215 use Bio::Ontology::RelationshipFactory;
  1         2  
  1         21  
86 1     1   5 use Data::Dumper;
  1         2  
  1         36  
87              
88 1     1   4 use base qw(Bio::Root::Root Bio::Ontology::OntologyEngineI);
  1         2  
  1         2086  
89              
90             =head2 new
91              
92             Title : new
93             Usage : $soe = Bio::Ontology::SimpleOntologyEngine->new;
94             Function: Initializes the ontology engine.
95             Example : $soe = Bio::Ontology::SimpleOntologyEngine->new;
96             Returns : Object of class SimpleOntologyEngine.
97             Args :
98              
99             =cut
100              
101             sub new {
102 1     1 1 7 my ( $class, @args ) = @_;
103 1         5 my $self = $class->SUPER::new(@args);
104              
105             # my %param = @args;
106              
107 1         4 $self->_term_store( {} );
108 1         3 $self->_relationship_store( {} );
109 1         9 $self->_inverted_relationship_store( {} );
110 1         2 $self->_relationship_type_store( {} );
111 1         3 $self->_instantiated_terms_store( {} );
112              
113             # set defaults for the factories
114 1         5 $self->relationship_factory(
115             Bio::Ontology::RelationshipFactory->new( -type => "Bio::Ontology::Relationship" ) );
116 1         2 return $self;
117             }
118              
119             =head2 _instantiated_terms_store
120              
121             Title : _instantiated_terms_store
122             Usage : $obj->_instantiated_terms_store($newval)
123             Function:
124             Example :
125             Returns : hash
126             Args : empty hash
127              
128             =cut
129              
130             sub _instantiated_terms_store {
131 24     24   32 my ( $self, $value ) = @_;
132              
133 24 100       30 if ( defined $value ) {
134 1         2 $self->{'_instantiated_terms_store'} = $value;
135             }
136 24         46 return $self->{'_instantiated_terms_store'};
137             }
138              
139             =head2 mark_instantiated
140              
141             Title : mark_instantiated
142             Usage : $self->mark_instantiated(TermI terms): TermI
143             Function: Marks TermI objects as fully instantiated,
144             allowing for proper counting of the number of terms in the term store.
145             The TermI objects has to be already stored in the term store in order
146             to be marked.
147             Example : $self->mark_instantiated($term);
148             Returns : its argument or throws an exception if a term is not
149             in the term store.
150             Args : array of objects of class TermI.
151              
152             =cut
153              
154             sub mark_instantiated {
155 0     0 1 0 my ( $self, @terms ) = @_;
156              
157 0         0 foreach my $term (@terms) {
158             $self->throw( "term " . $term->identifier . " not in the term store\n" )
159 0 0       0 if !defined $self->_term_store->{ $term->identifier };
160 0         0 $self->_instantiated_terms_store->{ $term->identifier } = 1;
161             }
162              
163 0         0 return @terms;
164             }
165              
166             =head2 mark_uninstantiated
167              
168             Title : mark_uninstantiated
169             Usage : $self->mark_uninstantiated(TermI terms): TermI
170             Function: Marks TermI objects as not fully instantiated,
171             Example : $self->mark_uninstantiated($term);
172             Returns : its argument or throws an exception if a term is not
173             in the term store(if the term is not marked it does nothing).
174             Args : array of objects of class TermI.
175              
176             =cut
177              
178             sub mark_uninstantiated {
179 0     0 1 0 my ( $self, @terms ) = @_;
180              
181 0         0 foreach my $term (@terms) {
182             $self->throw( "term " . $term->identifier . " not in the term store\n" )
183 0 0       0 if !defined $self->_term_store->{ $term->identifier };
184             delete $self->_instantiated_terms_store->{ $term->identifier }
185 0 0       0 if defined $self->_instantiated_terms_store->{ $term->identifier };
186             }
187              
188 0         0 return @terms;
189             }
190              
191             =head2 _term_store
192              
193             Title : term_store
194             Usage : $obj->_term_store($newval)
195             Function:
196             Example :
197             Returns : reference to an array of Bio::Ontology::TermI objects
198             Args : reference to an array of Bio::Ontology::TermI objects
199              
200             =cut
201              
202             sub _term_store {
203 28     28   34 my ( $self, $value ) = @_;
204              
205 28 100       38 if ( defined $value ) {
206 1 50       6 if ( defined $self->{'_term_store'} ) {
207 0         0 $self->throw("_term_store already defined\n");
208             } else {
209 1         2 $self->{'_term_store'} = $value;
210             }
211             }
212              
213 28         38 return $self->{'_term_store'};
214             }
215              
216             =head2 add_term
217              
218             Title : add_term
219             Usage : add_term(TermI term): TermI
220             Function: Adds TermI object to the ontology engine term store.
221             Marks the term fully instantiated by default.
222             Example : $soe->add_term($term)
223             Returns : its argument.
224             Args : object of class TermI.
225              
226             =cut
227              
228             sub add_term {
229 4     4 1 6 my ( $self, $term ) = @_;
230 4         6 my $term_store = $self->_term_store;
231              
232 4 50 33     8 if ( defined $term_store->{ $term->identifier } && $self->_instantiated_terms_store->{ $term->identifier }) {
233 0         0 $self->throw( "term " . $term->identifier . " already defined\n" );
234             } else {
235 4         6 $term_store->{ $term->identifier } = $term;
236 4         8 $self->_instantiated_terms_store->{ $term->identifier } = 1;
237             }
238              
239 4         9 return $term;
240             }
241              
242             =head2 get_term_by_identifier
243              
244             Title : get_term_by_identifier
245             Usage : get_term_by_identifier(String id): TermI
246             Function: Retrieves terms from the term store by their identifier
247             field, or an empty list if not there.
248             Example : $term = $soe->get_term_by_identifier("IPR000001");
249             Returns : An array of zero or more Bio::Ontology::TermI objects.
250             Args : An array of identifier strings
251              
252             =cut
253              
254             sub get_term_by_identifier {
255 10     10 1 18 my ( $self, @ids ) = @_;
256 10         11 my @ans = ();
257              
258 10         12 foreach my $id (@ids) {
259 21         27 my $term = $self->_term_store->{$id};
260 21 50       35 push @ans, $term if defined $term;
261             }
262              
263 10         22 return @ans;
264             }
265              
266             =head2 _get_number_rels
267              
268             Title : get_number_rels
269             Usage :
270             Function:
271             Example :
272             Returns :
273             Args :
274              
275             =cut
276              
277             sub _get_number_rels {
278 0     0   0 my ($self) = @_;
279 0         0 my $num_rels = 0;
280              
281 0         0 foreach my $entry ( $self->_relationship_store ) {
282 0         0 $num_rels += scalar keys %$entry;
283             }
284 0         0 return $num_rels;
285             }
286              
287             =head2 _get_number_terms
288              
289             Title : _get_number_terms
290             Usage :
291             Function:
292             Example :
293             Returns :
294             Args :
295              
296             =cut
297              
298             sub _get_number_terms {
299 0     0   0 my ($self) = @_;
300              
301 0         0 return scalar $self->_filter_unmarked( values %{ $self->_term_store } );
  0         0  
302              
303             }
304              
305             =head2 _relationship_store
306              
307             Title : _storerelationship_store
308             Usage : $obj->relationship_store($newval)
309             Function:
310             Example :
311             Returns : reference to an array of Bio::Ontology::TermI objects
312             Args : reference to an array of Bio::Ontology::TermI objects
313              
314             =cut
315              
316             sub _relationship_store {
317 19     19   28 my ( $self, $value ) = @_;
318              
319 19 100       32 if ( defined $value ) {
320 1 50       3 if ( defined $self->{'_relationship_store'} ) {
321 0         0 $self->throw("_relationship_store already defined\n");
322             } else {
323 1         2 $self->{'_relationship_store'} = $value;
324             }
325             }
326              
327 19         43 return $self->{'_relationship_store'};
328             }
329              
330             =head2 _inverted_relationship_store
331              
332             Title : _inverted_relationship_store
333             Usage :
334             Function:
335             Example :
336             Returns : reference to an array of Bio::Ontology::TermI objects
337             Args : reference to an array of Bio::Ontology::TermI objects
338              
339             =cut
340              
341             sub _inverted_relationship_store {
342 13     13   17 my ( $self, $value ) = @_;
343              
344 13 100       20 if ( defined $value ) {
345 1 50       2 if ( defined $self->{'_inverted_relationship_store'} ) {
346 0         0 $self->throw("_inverted_relationship_store already defined\n");
347             } else {
348 1         2 $self->{'_inverted_relationship_store'} = $value;
349             }
350             }
351              
352 13         24 return $self->{'_inverted_relationship_store'};
353             }
354              
355             =head2 _relationship_type_store
356              
357             Title : _relationship_type_store
358             Usage : $obj->_relationship_type_store($newval)
359             Function:
360             Example :
361             Returns : reference to an array of Bio::Ontology::RelationshipType objects
362             Args : reference to an array of Bio::Ontology::RelationshipType objects
363              
364             =cut
365              
366             sub _relationship_type_store {
367 5     5   6 my ( $self, $value ) = @_;
368              
369 5 100       8 if ( defined $value ) {
370 1 50       2 if ( defined $self->{'_relationship_type_store'} ) {
371 0         0 $self->throw("_relationship_type_store already defined\n");
372             } else {
373 1         2 $self->{'_relationship_type_store'} = $value;
374             }
375             }
376              
377 5         9 return $self->{'_relationship_type_store'};
378             }
379              
380             =head2 _add_relationship_simple
381              
382             Title : _add_relationship_simple
383             Usage :
384             Function:
385             Example :
386             Returns :
387             Args :
388              
389             =cut
390              
391             sub _add_relationship_simple {
392 12     12   16 my ( $self, $store, $rel, $inverted ) = @_;
393              
394 12 100       21 my $subject = $rel->subject_term
395             or $self->throw('cannot add relationship, relationship has no subject_term');
396 10 100       17 my $object = $rel->object_term
397             or $self->throw('cannot add relationship, relationship has no object_term');
398              
399 8         12 my ( $parent_id, $child_id ) = ( $object->identifier, $subject->identifier );
400 8 100       16 ( $parent_id, $child_id ) = ( $child_id, $parent_id ) if $inverted;
401              
402 8 50 66     19 if ( defined $store->{$parent_id}
      33        
403             && defined $store->{$parent_id}->{$child_id}
404             && $store->{$parent_id}->{$child_id}->name ne $rel->predicate_term->name
405             ) {
406             $self->throw( "relationship "
407             . $rel->predicate_term->name
408             . " between "
409             . $parent_id . " and "
410             . $child_id
411             . " already defined as "
412 0         0 . $store->{$parent_id}->{$child_id}->name
413             . "\n" );
414             }
415              
416             # all is well if we get here
417 8         13 $store->{$parent_id}->{$child_id} = $rel->predicate_term;
418             }
419              
420             =head2 add_relationship
421              
422             Title : add_relationship
423             Usage : add_relationship(RelationshipI relationship): RelationshipI
424             Function: Adds a relationship object to the ontology engine.
425             Example :
426             Returns : Its argument.
427             Args : A RelationshipI object.
428              
429             =cut
430              
431             sub add_relationship {
432 8     8 1 12 my ( $self, $rel ) = @_;
433              
434 8         14 $self->_add_relationship_simple( $self->_relationship_store, $rel, 0 );
435 4         6 $self->_add_relationship_simple( $self->_inverted_relationship_store, $rel, 1 );
436 4         7 $self->_relationship_type_store->{ $self->_unique_termid( $rel->predicate_term ) } =
437             $rel->predicate_term;
438              
439 4         9 return $rel;
440             }
441              
442             =head2 get_relationships
443              
444             Title : get_relationships
445             Usage : get_relationships(): RelationshipI
446             Function: Retrieves all relationship objects.
447             Example :
448             Returns : Array of RelationshipI objects
449             Args :
450              
451             =cut
452              
453             sub get_relationships {
454 0     0 1 0 my $self = shift;
455 0         0 my $term = shift;
456 0         0 my @rels;
457 0         0 my $store = $self->_relationship_store;
458 0         0 my $relfact = $self->relationship_factory();
459              
460             my @parent_ids = $term
461             ?
462              
463             # if a term is supplied then only get the term's parents
464 0         0 ( map { $_->identifier(); } $self->get_parent_terms($term) )
465             :
466              
467             # otherwise use all parent ids
468 0 0       0 ( keys %{$store} );
  0         0  
469              
470             # add the term as a parent too if one is supplied
471 0 0       0 push( @parent_ids, $term->identifier ) if $term;
472              
473 0         0 foreach my $parent_id (@parent_ids) {
474 0         0 my $parent_entry = $store->{$parent_id};
475              
476             # if a term is supplied, add a relationship for the parent to the term
477             # except if the parent is the term itself (we added that one before)
478 0 0 0     0 if ( $term && ( $parent_id ne $term->identifier() ) ) {
479 0         0 my @parent_terms = $self->get_term_by_identifier($parent_id);
480 0         0 foreach my $parent_term (@parent_terms) {
481             push(
482             @rels,
483             $relfact->create_object(
484             -object_term => $parent_term,
485             -subject_term => $term,
486 0         0 -predicate_term => $parent_entry->{ $term->identifier },
487             -ontology => $term->ontology()
488             )
489             );
490             }
491              
492             } else {
493              
494             # otherwise, i.e., no term supplied, or the parent equals the
495             # supplied term
496 0 0       0 my @parent_terms = $term ? ($term) : $self->get_term_by_identifier($parent_id);
497 0         0 foreach my $child_id ( keys %$parent_entry ) {
498 0         0 my $rel_info = $parent_entry->{$child_id};
499 0         0 my ($subj_term) = $self->get_term_by_identifier($child_id);
500              
501 0         0 foreach my $parent_term (@parent_terms) {
502 0         0 push(
503             @rels,
504             $relfact->create_object(
505             -object_term => $parent_term,
506             -subject_term => $subj_term,
507             -predicate_term => $rel_info,
508             -ontology => $parent_term->ontology
509             )
510             );
511             }
512             }
513             }
514             }
515              
516 0         0 return @rels;
517             }
518              
519             =head2 get_all_relationships
520              
521             Title : get_all_relationships
522             Usage : get_all_relationships(): RelationshipI
523             Function: Retrieves all relationship objects.
524             Example :
525             Returns : Array of RelationshipI objects
526             Args :
527              
528             =cut
529              
530             sub get_all_relationships {
531 0     0 1 0 return shift->get_relationships();
532             }
533              
534             =head2 get_predicate_terms
535              
536             Title : get_predicate_terms
537             Usage : get_predicate_terms(): TermI
538             Function: Retrieves all relationship types stored in the engine
539             Example :
540             Returns : reference to an array of Bio::Ontology::RelationshipType objects
541             Args :
542              
543             =cut
544              
545             sub get_predicate_terms {
546 0     0 1 0 my ($self) = @_;
547              
548 0         0 return values %{ $self->_relationship_type_store };
  0         0  
549             }
550              
551             =head2 _is_rel_type
552              
553             Title : _is_rel_type
554             Usage :
555             Function:
556             Example :
557             Returns :
558             Args :
559              
560             =cut
561              
562             sub _is_rel_type {
563 16     16   19 my ( $self, $term, @rel_types ) = @_;
564              
565 16         18 foreach my $rel_type (@rel_types) {
566 16 50 33     32 if ( $rel_type->identifier || $term->identifier ) {
567 0 0       0 return 1 if $rel_type->identifier eq $term->identifier;
568             } else {
569 16 100       23 return 1 if $rel_type->name eq $term->name;
570             }
571             }
572              
573 6         12 return 0;
574             }
575              
576             =head2 _typed_traversal
577              
578             Title : _typed_traversal
579             Usage :
580             Function:
581             Example :
582             Returns :
583             Args :
584              
585             =cut
586              
587             sub _typed_traversal {
588 18     18   27 my ( $self, $rel_store, $level, $term_id, @rel_types ) = @_;
589 18 50       31 return if !defined( $rel_store->{$term_id} );
590 18         18 my %parent_entry = %{ $rel_store->{$term_id} };
  18         40  
591 18         34 my @children = keys %parent_entry;
592              
593 18         18 my @ans;
594              
595 18 100       31 if ( @rel_types > 0 ) {
596 10         10 @ans = ();
597              
598 10         11 foreach my $child_id (@children) {
599             push @ans, $child_id
600 16 100       28 if $self->_is_rel_type( $rel_store->{$term_id}->{$child_id}, @rel_types );
601             }
602             } else {
603 8         10 @ans = @children;
604             }
605 18 100       31 if ( $level < 1 ) {
606 14         55 my @ans1 = ();
607              
608 14         15 foreach my $child_id (@ans) {
609             push @ans1, $self->_typed_traversal( $rel_store, $level - 1, $child_id, @rel_types )
610 16 100       37 if defined $rel_store->{$child_id};
611             }
612 14         47 push @ans, @ans1;
613             }
614              
615 18         44 return @ans;
616             }
617              
618             =head2 get_child_terms
619              
620             Title : get_child_terms
621             Usage : get_child_terms(TermI term, TermI predicate_terms): TermI
622             get_child_terms(TermI term, RelationshipType predicate_terms): TermI
623             Function: Retrieves all child terms of a given term, that satisfy a
624             relationship among those that are specified in the second
625             argument or undef otherwise. get_child_terms is a special
626             case of get_descendant_terms, limiting the search to the
627             direct descendants.
628             Example :
629             Returns : Array of TermI objects.
630             Args : First argument is the term of interest, second is the list of
631             relationship type terms.
632              
633             =cut
634              
635             sub get_child_terms {
636 3     3 1 6 my ( $self, $term, @relationship_types ) = @_;
637              
638 3 50 33     29 $self->throw("must provide TermI compliant object")
639             unless defined($term) && $term->isa("Bio::Ontology::TermI");
640              
641 3         7 return $self->_filter_unmarked(
642             $self->get_term_by_identifier(
643             $self->_typed_traversal(
644             $self->_relationship_store, 1, $term->identifier, @relationship_types
645             )
646             )
647             );
648             }
649              
650             =head2 get_descendant_terms
651              
652             Title : get_descendant_terms
653             Usage : get_descendant_terms(TermI term, TermI rel_types): TermI
654             get_child_terms(TermI term, RelationshipType predicate_terms): TermI
655             Function: Retrieves all descendant terms of a given term, that
656             satisfy a relationship among those that are specified in
657             the second argument or undef otherwise. Uses
658             _typed_traversal to find all descendants.
659              
660             Example :
661             Returns : Array of TermI objects.
662             Args : First argument is the term of interest, second is the list of
663             relationship type terms.
664              
665             =cut
666              
667             sub get_descendant_terms {
668 3     3 1 6 my ( $self, $term, @relationship_types ) = @_;
669              
670 3 50 33     15 $self->throw("must provide TermI compliant object")
671             unless defined($term) && $term->isa("Bio::Ontology::TermI");
672              
673 3         8 return $self->_filter_unmarked(
674             $self->_filter_repeated(
675             $self->get_term_by_identifier(
676             $self->_typed_traversal(
677             $self->_relationship_store, 0, $term->identifier, @relationship_types
678             )
679             )
680             )
681             );
682             }
683              
684             =head2 get_parent_terms
685              
686             Title : get_parent_terms
687             Usage : get_parent_terms(TermI term, TermI predicate_terms): TermI
688             get_child_terms(TermI term, RelationshipType predicate_terms): TermI
689             Function: Retrieves all parent terms of a given term, that satisfy a
690             relationship among those that are specified in the second
691             argument or undef otherwise. get_parent_terms is a special
692             case of get_ancestor_terms, limiting the search to the
693             direct ancestors.
694              
695             Example :
696             Returns : Array of TermI objects.
697             Args : First argument is the term of interest, second is the list of relationship type terms.
698              
699             =cut
700              
701             sub get_parent_terms {
702 1     1 1 3 my ( $self, $term, @relationship_types ) = @_;
703 1 50       3 $self->throw("term must be a valid object, not undef") unless defined $term;
704              
705 1         3 return $self->_filter_unmarked(
706             $self->get_term_by_identifier(
707             $self->_typed_traversal(
708             $self->_inverted_relationship_store,
709             1, $term->identifier, @relationship_types
710             )
711             )
712             );
713             }
714              
715             =head2 get_ancestor_terms
716              
717             Title : get_ancestor_terms
718             Usage : get_ancestor_terms(TermI term, TermI predicate_terms): TermI
719             get_child_terms(TermI term, RelationshipType predicate_terms): TermI
720             Function: Retrieves all ancestor terms of a given term, that satisfy
721             a relationship among those that are specified in the second
722             argument or undef otherwise. Uses _typed_traversal to find
723             all ancestors.
724              
725             Example :
726             Returns : Array of TermI objects.
727             Args : First argument is the term of interest, second is the list
728             of relationship type terms.
729              
730             =cut
731              
732             sub get_ancestor_terms {
733 3     3 1 6 my ( $self, $term, @relationship_types ) = @_;
734 3 50       6 $self->throw("term must be a valid object, not undef") unless defined $term;
735              
736 3         7 return $self->_filter_unmarked(
737             $self->_filter_repeated(
738             $self->get_term_by_identifier(
739             $self->_typed_traversal(
740             $self->_inverted_relationship_store, 0,
741             $term->identifier, @relationship_types
742             )
743             )
744             )
745             );
746             }
747              
748             =head2 get_leaf_terms
749              
750             Title : get_leaf_terms
751             Usage : get_leaf_terms(): TermI
752             Function: Retrieves all leaf terms from the ontology. Leaf term is a term w/o descendants.
753             Example : @leaf_terms = $obj->get_leaf_terms()
754             Returns : Array of TermI objects.
755             Args :
756              
757             =cut
758              
759             sub get_leaf_terms {
760 1     1 1 2 my ($self) = @_;
761 1         2 my @leaf_terms;
762              
763 1         2 foreach my $term ( values %{ $self->_term_store } ) {
  1         2  
764             push @leaf_terms, $term
765             if !defined $self->_relationship_store->{ $term->identifier }
766 4 100 66     6 && defined $self->_instantiated_terms_store->{ $term->identifier };
767             }
768              
769 1         2 return @leaf_terms;
770             }
771              
772             =head2 get_root_terms
773              
774             Title : get_root_terms
775             Usage : get_root_terms(): TermI
776             Function: Retrieves all root terms from the ontology. Root term is a term w/o descendants.
777             Example : @root_terms = $obj->get_root_terms()
778             Returns : Array of TermI objects.
779             Args :
780              
781             =cut
782              
783             sub get_root_terms {
784 1     1 1 2 my ($self) = @_;
785 1         2 my @root_terms;
786              
787 1         2 foreach my $term ( values %{ $self->_term_store } ) {
  1         2  
788             push @root_terms, $term
789             if !defined $self->_inverted_relationship_store->{ $term->identifier }
790 4 100 66     7 && defined $self->_instantiated_terms_store->{ $term->identifier };
791             }
792              
793 1         3 return @root_terms;
794             }
795              
796             =head2 _filter_repeated
797              
798             Title : _filter_repeated
799             Usage : @lst = $self->_filter_repeated(@old_lst);
800             Function: Removes repeated terms
801             Example :
802             Returns : List of unique TermI objects
803             Args : List of TermI objects
804              
805             =cut
806              
807             sub _filter_repeated {
808 6     6   7 my ( $self, @args ) = @_;
809 6         8 my %h;
810              
811 6         7 foreach my $element (@args) {
812 16 100       24 $h{ $element->identifier } = $element if !defined $h{ $element->identifier };
813             }
814              
815 6         15 return values %h;
816             }
817              
818             =head2 get_all_terms
819              
820             Title : get_all_terms
821             Usage : get_all_terms(): TermI
822             Function: Retrieves all terms currently stored in the ontology.
823             Example : @all_terms = $obj->get_all_terms()
824             Returns : Array of TermI objects.
825             Args :
826              
827             =cut
828              
829             sub get_all_terms {
830 0     0 1 0 my ($self) = @_;
831              
832 0         0 return $self->_filter_unmarked( values %{ $self->_term_store } );
  0         0  
833             }
834              
835             =head2 find_terms
836              
837             Title : find_terms
838             Usage : ($term) = $oe->find_terms(-identifier => "SO:0000263");
839             Function: Find term instances matching queries for their attributes.
840              
841             This implementation can efficiently resolve queries by
842             identifier.
843              
844             Example :
845             Returns : an array of zero or more Bio::Ontology::TermI objects
846             Args : Named parameters. The following parameters should be recognized
847             by any implementations:
848              
849             -identifier query by the given identifier
850             -name query by the given name
851              
852             =cut
853              
854             sub find_terms {
855 0     0 1 0 my ( $self, @args ) = @_;
856 0         0 my @terms;
857              
858 0         0 my ( $id, $name ) = $self->_rearrange( [qw(IDENTIFIER NAME)], @args );
859              
860 0 0       0 if ( defined($id) ) {
861 0         0 @terms = $self->get_term_by_identifier($id);
862             } else {
863 0         0 @terms = $self->get_all_terms();
864             }
865 0 0       0 if ( defined($name) ) {
866 0         0 @terms = grep { $_->name() eq $name; } @terms;
  0         0  
867             }
868 0         0 return @terms;
869             }
870              
871             =head2 relationship_factory
872              
873             Title : relationship_factory
874             Usage : $fact = $obj->relationship_factory()
875             Function: Get/set the object factory to be used when relationship
876             objects are created by the implementation on-the-fly.
877              
878             Example :
879             Returns : value of relationship_factory (a Bio::Factory::ObjectFactoryI
880             compliant object)
881             Args : on set, a Bio::Factory::ObjectFactoryI compliant object
882              
883             =cut
884              
885             sub relationship_factory {
886 1     1 1 2 my $self = shift;
887              
888 1 50       3 return $self->{'relationship_factory'} = shift if @_;
889 0         0 return $self->{'relationship_factory'};
890             }
891              
892             =head2 term_factory
893              
894             Title : term_factory
895             Usage : $fact = $obj->term_factory()
896             Function: Get/set the object factory to be used when term objects are
897             created by the implementation on-the-fly.
898              
899             Note that this ontology engine implementation does not
900             create term objects on the fly, and therefore setting this
901             attribute is meaningless.
902              
903             Example :
904             Returns : value of term_factory (a Bio::Factory::ObjectFactoryI
905             compliant object)
906             Args : on set, a Bio::Factory::ObjectFactoryI compliant object
907              
908             =cut
909              
910             sub term_factory {
911 0     0 1 0 my $self = shift;
912              
913 0 0       0 if (@_) {
914 0         0 $self->warn(
915             "setting term factory, but " . ref($self) . " does not create terms on-the-fly" );
916 0         0 return $self->{'term_factory'} = shift;
917             }
918 0         0 return $self->{'term_factory'};
919             }
920              
921             =head2 _filter_unmarked
922              
923             Title : _filter_unmarked
924             Usage : _filter_unmarked(TermI terms): TermI
925             Function: Removes the uninstantiated terms from the list of terms
926             Example :
927             Returns : array of fully instantiated TermI objects
928             Args : array of TermI objects
929              
930             =cut
931              
932             sub _filter_unmarked {
933 10     10   13 my ( $self, @terms ) = @_;
934 10         14 my @filtered_terms = ();
935              
936 10 100       17 if ( scalar(@terms) >= 1 ) {
937 7         8 foreach my $term (@terms) {
938             push @filtered_terms, $term
939 17 50       27 if defined $self->_instantiated_terms_store->{ $term->identifier };
940             }
941             }
942              
943 10         80 return @filtered_terms;
944             }
945              
946             =head2 remove_term_by_id
947              
948             Title : remove_term_by_id
949             Usage : remove_term_by_id(String id): TermI
950             Function: Removes TermI object from the ontology engine using the
951             string id as an identifier. Current implementation does not
952             enforce consistency of the relationships using that term.
953             Example : $term = $soe->remove_term_by_id($id);
954             Returns : Object of class TermI or undef if not found.
955             Args : The string identifier of a term.
956              
957             =cut
958              
959             sub remove_term_by_id {
960 0     0 1 0 my ( $self, $id ) = @_;
961              
962 0 0       0 if ( $self->get_term_by_identifier($id) ) {
963 0         0 my $term = $self->{_term_store}->{$id};
964 0         0 delete $self->{_term_store}->{$id};
965 0         0 return $term;
966             } else {
967 0         0 $self->warn("Term with id '$id' is not in the term store");
968 0         0 return;
969             }
970             }
971              
972             =head2 to_string
973              
974             Title : to_string
975             Usage : print $sv->to_string();
976             Function: Currently returns formatted string containing the number of
977             terms and number of relationships from the ontology engine.
978             Example : print $sv->to_string();
979             Returns :
980             Args :
981              
982             =cut
983              
984             sub to_string {
985 0     0 1 0 my ($self) = @_;
986 0         0 my $s = "";
987              
988 0         0 $s .= "-- # Terms:\n";
989 0         0 $s .= scalar( $self->get_all_terms ) . "\n";
990 0         0 $s .= "-- # Relationships:\n";
991 0         0 $s .= $self->_get_number_rels . "\n";
992              
993 0         0 return $s;
994             }
995              
996             =head2 _unique_termid
997              
998             Title : _unique_termid
999             Usage :
1000             Function: Returns a string that can be used as ID using fail-over
1001             approaches.
1002              
1003             If the identifier attribute is not set, it uses the
1004             combination of name and ontology name, provided both are
1005             set. If they are not, it returns the name alone.
1006              
1007             Note that this is a private method. Call from inheriting
1008             classes but not from outside.
1009              
1010             Example :
1011             Returns : a string
1012             Args : a Bio::Ontology::TermI compliant object
1013              
1014             =cut
1015              
1016             sub _unique_termid {
1017 4     4   5 my $self = shift;
1018 4         4 my $term = shift;
1019              
1020 4 50       8 return $term->identifier() if $term->identifier();
1021 4 50       8 my $id = $term->ontology->name() if $term->ontology();
1022 4 50       9 if ($id) {
1023 4         6 $id .= '|';
1024             } else {
1025 0         0 $id = '';
1026             }
1027 4         8 $id .= $term->name();
1028             }
1029              
1030             #################################################################
1031             # aliases
1032             #################################################################
1033              
1034             *get_relationship_types = \&get_predicate_terms;
1035              
1036             1;