3 # BioPerl module for Bio::Ontology::OBOEngine
5 # POD documentation - main docs before the code
9 Bio::Ontology::OBOEngine - An Ontology Engine for OBO style flat file
10 format from the Gene Ontology Consortium
14 use Bio::Ontology::OBOEngine;
16 my $parser = Bio::Ontology::OBOEngine->new
17 ( -file => "gene_ontology.obo" );
19 my $engine = $parser->parse();
23 Needs Graph.pm from CPAN.
25 This module replaces SimpleGOEngine.pm, which is deprecated.
31 User feedback is an integral part of the evolution of this and other
32 Bioperl modules. Send your comments and suggestions preferably to the
33 Bioperl mailing lists Your participation is much appreciated.
35 bioperl-l@bioperl.org - General discussion
36 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
40 Please direct usage questions or support issues to the mailing list:
42 L<bioperl-l@bioperl.org>
44 rather than to the module maintainer directly. Many experienced and
45 reponsive experts will be able look at the problem and quickly
46 address it. Please include a thorough description of the problem
47 with code and data examples if at all possible.
51 Report bugs to the Bioperl bug tracking system to help us keep track
52 the bugs and their resolution. Bug reports can be submitted via
55 http://bugzilla.open-bio.org/
61 Email: s-merchant@northwestern.edu
65 Northwestern University
66 Center for Genetic Medicine (CGM), dictyBase
73 Hilmar Lapp, hlapp at gmx.net
74 Chris Mungall, cjm at fruitfly.org
78 The rest of the documentation details each of the object
79 methods. Internal methods are usually preceded with a _
83 package Bio
::Ontology
::OBOEngine
;
85 use Bio
::Ontology
::SimpleGOEngine
::GraphAdaptor
;
88 use Bio
::Ontology
::RelationshipType
;
89 use Bio
::Ontology
::RelationshipFactory
;
92 use constant TRUE
=> 1;
93 use constant FALSE
=> 0;
94 use constant IS_A
=> "IS_A";
95 use constant PART_OF
=> "PART_OF";
96 use constant RELATED_TO
=> "RELATED_TO";
97 use constant TERM
=> "TERM";
98 use constant TYPE
=> "TYPE";
99 use constant ONTOLOGY
=> "ONTOLOGY";
100 use constant REGULATES
=> "REGULATES";
101 use constant POSITIVELY_REGULATES
=> "POSITIVELY_REGULATES";
102 use constant NEGATIVELY_REGULATES
=> "NEGATIVELY_REGULATES";
105 use base
qw(Bio::Root::Root Bio::Ontology::OntologyEngineI);
112 Usage : $engine = Bio::Ontology::OBOEngine->new()
113 Function: Creates a new OBOEngine
114 Returns : A new OBOEngine object
120 my( $class, @args ) = @_;
122 my $self = $class->SUPER::new
( @args );
134 Usage : $engine->init();
135 Function: Initializes this Engine.
144 $self->{ "_is_a_relationship" } = Bio
::Ontology
::RelationshipType
->get_instance( IS_A
);
145 $self->{ "_part_of_relationship" } = Bio
::Ontology
::RelationshipType
->get_instance( PART_OF
);
146 $self->{ "_related_to_relationship" } = Bio
::Ontology
::RelationshipType
->get_instance( RELATED_TO
);
148 $self->{'_regulates_relationship'} = Bio
::Ontology
::RelationshipType
->get_instance(REGULATES
);
149 $self->{'_positively_regulate'} = Bio
::Ontology
::RelationshipType
->get_instance(POSITIVELY_REGULATES
);
150 $self->{'_negatively_regulate'} = Bio
::Ontology
::RelationshipType
->get_instance(NEGATIVELY_REGULATES
);
153 $self->graph( Bio
::Ontology
::SimpleGOEngine
::GraphAdaptor
->new() ); # NG 05-02-16
155 # set defaults for the factories
156 $self->relationship_factory(Bio
::Ontology
::RelationshipFactory
->new(
157 -type
=> "Bio::Ontology::Relationship"));
163 =head2 is_a_relationship
165 Title : is_a_relationship()
166 Usage : $IS_A = $engine->is_a_relationship();
167 Function: Returns a Bio::Ontology::RelationshipType object for "is-a"
169 Returns : Bio::Ontology::RelationshipType set to "IS_A"
174 sub is_a_relationship
{
175 my ( $self, $value ) = @_;
177 if ( defined $value ) {
178 $self->throw( "Attempted to change immutable field" );
181 return $self->{ "_is_a_relationship" };
182 } # is_a_relationship
186 =head2 part_of_relationship
188 Title : part_of_relationship()
189 Usage : $PART_OF = $engine->part_of_relationship();
190 Function: Returns a Bio::Ontology::RelationshipType object for "part-of"
192 Returns : Bio::Ontology::RelationshipType set to "PART_OF"
197 sub part_of_relationship
{
198 my ( $self, $value ) = @_;
200 if ( defined $value ) {
201 $self->throw( "Attempted to change immutable field" );
204 return $self->{ "_part_of_relationship" };
205 } # part_of_relationship
208 =head2 related_to_relationship
210 Title : related_to_relationship()
211 Usage : $RELATED_TO = $engine->related_to_relationship();
212 Function: Returns a Bio::Ontology::RelationshipType object for "related-to"
214 Returns : Bio::Ontology::RelationshipType set to "RELATED_TO"
219 sub related_to_relationship
{
220 my ( $self, $value ) = @_;
222 if ( defined $value ) {
223 $self->throw( "Attempted to change immutable field" );
226 return $self->{ "_related_to_relationship" };
227 } # related_to_relationship
229 =head2 regulates_relationship
231 Title : regulates_relationship()
232 Usage : $REGULATES = $engine->regulates_relationship();
233 Function: Returns a Bio::Ontology::RelationshipType object for "regulates"
235 Returns : Bio::Ontology::RelationshipType set to "REGULATES"
240 sub regulates_relationship
{
241 my ( $self, $value ) = @_;
243 if ( defined $value ) {
244 $self->throw( "Attempted to change immutable field" );
247 return $self->{ "_regulates_relationship" };
248 } # is_a_relationship
250 =head2 positively_regulates_relationship
252 Title : positively_regulates_relationship()
253 Usage : $REGULATES = $engine->positively_regulates_relationship();
254 Function: Returns a Bio::Ontology::RelationshipType object for "positively_regulates"
256 Returns : Bio::Ontology::RelationshipType set to "POSITIVELY_REGULATES"
261 sub positively_regulates_relationship
{
262 my ( $self, $value ) = @_;
264 if ( defined $value ) {
265 $self->throw( "Attempted to change immutable field" );
268 return $self->{ "_positively_regulate" };
271 =head2 negatively_regulates_relationship
273 Title : negatively_regulates_relationship()
274 Usage : $REGULATES = $engine->negatively_regulates_relationship();
275 Function: Returns a Bio::Ontology::RelationshipType object for "negatively_regulates"
277 Returns : Bio::Ontology::RelationshipType set to "POSITIVELY_REGULATES"
282 sub negatively_regulates_relationship
{
283 my ( $self, $value ) = @_;
285 if ( defined $value ) {
286 $self->throw( "Attempted to change immutable field" );
289 return $self->{ "_negatively_regulate" };
296 Usage : $engine->add_term( $term_obj );
297 Function: Adds a Bio::Ontology::TermI to this engine
298 Returns : true if the term was added and false otherwise (e.g., if the
299 term already existed in the ontology engine)
300 Args : Bio::Ontology::TermI
305 my ( $self, $term ) = @_;
307 return FALSE
if $self->has_term( $term );
309 my $goid = $self->_get_id($term);
311 $self->graph()->add_vertex( $goid );
312 $self->graph()->set_vertex_attribute( $goid, TERM
, $term ); # NG 05-02-16
322 Usage : $engine->has_term( $term );
323 Function: Checks whether this engine contains a particular term
324 Returns : true or false
325 Args : Bio::Ontology::TermI
327 Term identifier (e.g. "GO:0012345")
332 my ( $self, $term ) = @_;
333 $term = $self->_get_id( $term );
334 if ( $self->graph()->has_vertex( $term ) ) {
344 =head2 add_relationship_type
346 Title : add_relationship_type
347 Usage : $engine->add_relationship_type( $type_name, $ont );
348 Function: Adds a new relationship type to the engine. Use
349 get_relationship_type($type_name) to retrieve.
350 Returns : true if successfully added, false otherwise
351 Args : relationship type name to add (scalar)
352 ontology to which to assign the relationship type
356 sub add_relationship_type
{
357 my ($self,@args) = @_;
360 my $type_name = $args[0];
362 $self->{ "_extra_relationship_types" }{$type_name} = Bio
::Ontology
::RelationshipType
->get_instance($type_name,$ont);
363 #warn Dumper($self->{"_extra_relationship_types"}{$type_name});
370 =head2 get_relationship_type
372 Title : get_relationship_type
373 Usage : $engine->get_relationship_type( $type_name );
374 Function: Gets a Bio::Ontology::RelationshipI object corresponding
376 Returns : a Bio::Ontology::RelationshipI object
381 sub get_relationship_type
{
382 my ($self,$type_name) = @_;
383 return $self->{ "_extra_relationship_types" }{$type_name};
386 =head2 add_relationship
388 Title : add_relationship
389 Usage : $engine->add_relationship( $relationship );
390 $engine->add_relatioship( $subject_term, $predicate_term,
391 $object_term, $ontology );
392 $engine->add_relatioship( $subject_id, $predicate_id,
393 $object_id, $ontology);
394 Function: Adds a relationship to this engine
395 Returns : true if successfully added, false otherwise
396 Args : The relationship in one of three ways:
398 a) subject (or child) term id, Bio::Ontology::TermI
399 (rel.type), object (or parent) term id, ontology
403 b) subject Bio::Ontology::TermI, predicate
404 Bio::Ontology::TermI (rel.type), object
405 Bio::Ontology::TermI, ontology
409 c) Bio::Ontology::RelationshipI-compliant object
413 # term objs or term ids
414 sub add_relationship
{
415 my ( $self, $child, $type, $parent, $ont ) = @_;
417 if ( scalar( @_ ) == 2 ) {
418 $self->_check_class( $child, "Bio::Ontology::RelationshipI" );
419 $type = $child->predicate_term();
420 $parent = $child->object_term();
421 $ont = $child->ontology();
422 $child = $child->subject_term();
426 $self->_check_class( $type, "Bio::Ontology::TermI" );
428 my $parentid = $self->_get_id( $parent );
429 my $childid = $self->_get_id( $child );
431 my $g = $self->graph();
433 $self->add_term($child) unless $g->has_vertex( $childid );
434 $self->add_term($parent) unless $g->has_vertex( $parentid );
436 # This prevents multi graphs.
437 if ( $g->has_edge( $parentid, $childid ) ) {
441 $g->add_edge( $parentid, $childid );
442 $g->set_edge_attribute( $parentid, $childid, TYPE
, $type ); # NG 05-02-16
443 $g->set_edge_attribute( $parentid, $childid, ONTOLOGY
, $ont ); # NG 05-02-16
452 =head2 get_relationships
455 Title : get_relationships
456 Usage : $engine->get_relationships( $term );
457 Function: Returns all relationships of a term, or all relationships in
458 the graph if no term is specified.
459 Returns : Relationship
466 sub get_relationships
{
467 my ( $self, $term ) = @_;
469 my $g = $self->graph();
471 # obtain the ID if term provided
474 $termid = $self->_get_id( $term );
475 # check for presence in the graph
476 if ( ! $g->has_vertex( $termid ) ) {
477 $self->throw( "no term with identifier \"$termid\" in ontology" );
481 # now build the relationships
482 my $relfact = $self->relationship_factory();
483 # we'll build the relationships from edges
485 my @edges = $termid ?
$g->edges_at( $termid ) : $g->edges(); # NG 05-02-13
487 my ( $startid, $endid ) = @
{ shift @edges }; # NG 05-02-16
488 my $rel = $relfact->create_object
489 (-subject_term
=> $self->get_terms($endid),
490 -object_term
=> $self->get_terms($startid),
491 -predicate_term
=> $g->get_edge_attribute($startid, $endid, TYPE
),
492 -ontology
=> $g->get_edge_attribute($startid, $endid, ONTOLOGY
));
499 } # get_relationships
501 =head2 get_all_relationships
504 Title : get_all_relationships
505 Usage : @rels = $engine->get_all_relationships();
506 Function: Returns all relationships in the graph.
507 Returns : Relationship
512 sub get_all_relationships
{
513 return shift->get_relationships(@_);
514 } # get_all_relationships
518 =head2 get_predicate_terms
520 Title : get_predicate_terms
521 Usage : $engine->get_predicate_terms();
522 Function: Returns the types of relationships this engine contains
523 Returns : Bio::Ontology::RelationshipType
528 sub get_predicate_terms
{
532 $self->is_a_relationship(),
533 $self->part_of_relationship(),
534 $self->related_to_relationship(),
535 $self->regulates_relationship(),
536 $self->positively_regulates_relationship(),
537 $self->negatively_regulates_relationship(),
540 foreach my $termname (keys %{$self->{ "_extra_relationship_types" }}){
541 push @a, $self->{ "_extra_relationship_types" }{ $termname };
545 } # get_predicate_terms
550 =head2 get_child_terms
552 Title : get_child_terms
553 Usage : $engine->get_child_terms( $term_obj, @rel_types );
554 $engine->get_child_terms( $term_id, @rel_types );
555 Function: Returns the children of this term
556 Returns : Bio::Ontology::TermI
557 Args : Bio::Ontology::TermI, Bio::Ontology::RelationshipType
559 term id, Bio::Ontology::RelationshipType
561 if NO Bio::Ontology::RelationshipType is indicated: children
562 of ALL types are returned
566 sub get_child_terms
{
567 my ( $self, $term, @types ) = @_;
569 return $self->_get_child_parent_terms_helper( $term, TRUE
, @types );
574 =head2 get_descendant_terms
576 Title : get_descendant_terms
577 Usage : $engine->get_descendant_terms( $term_obj, @rel_types );
578 $engine->get_descendant_terms( $term_id, @rel_types );
579 Function: Returns the descendants of this term
580 Returns : Bio::Ontology::TermI
581 Args : Bio::Ontology::TermI, Bio::Ontology::RelationshipType
583 term id, Bio::Ontology::RelationshipType
585 if NO Bio::Ontology::RelationshipType is indicated:
586 descendants of ALL types are returned
590 sub get_descendant_terms
{
591 my ( $self, $term, @types ) = @_;
596 $term = $self->_get_id( $term );
598 if ( ! $self->graph()->has_vertex( $term ) ) {
599 $self->throw( "Ontology does not contain a term with an identifier of \"$term\"" );
602 $self->_get_descendant_terms_helper( $term, \
%ids, \
@types );
604 while( ( my $id ) = each ( %ids ) ) {
608 return $self->get_terms( @ids );
610 } # get_descendant_terms
613 =head2 get_parent_terms
615 Title : get_parent_terms
616 Usage : $engine->get_parent_terms( $term_obj, @rel_types );
617 $engine->get_parent_terms( $term_id, @rel_types );
618 Function: Returns the parents of this term
619 Returns : Bio::Ontology::TermI
620 Args : Bio::Ontology::TermI, Bio::Ontology::RelationshipType
622 term id, Bio::Ontology::RelationshipType
624 if NO Bio::Ontology::RelationshipType is indicated:
625 parents of ALL types are returned
629 sub get_parent_terms
{
630 my ( $self, $term, @types ) = @_;
632 return $self->_get_child_parent_terms_helper( $term, FALSE
, @types );
638 =head2 get_ancestor_terms
640 Title : get_ancestor_terms
641 Usage : $engine->get_ancestor_terms( $term_obj, @rel_types );
642 $engine->get_ancestor_terms( $term_id, @rel_types );
643 Function: Returns the ancestors of this term
644 Returns : Bio::Ontology::TermI
645 Args : Bio::Ontology::TermI, Bio::Ontology::RelationshipType
647 term id, Bio::Ontology::RelationshipType
649 if NO Bio::Ontology::RelationshipType is indicated:
650 ancestors of ALL types are returned
654 sub get_ancestor_terms
{
655 my ( $self, $term, @types ) = @_;
660 $term = $self->_get_id( $term );
662 if ( ! $self->graph()->has_vertex( $term ) ) {
663 $self->throw( "Ontology does not contain a term with an identifier of \"$term\"" );
666 $self->_get_ancestor_terms_helper( $term, \
%ids, \
@types );
668 while( ( my $id ) = each ( %ids ) ) {
672 return $self->get_terms( @ids );
674 } # get_ancestor_terms
680 =head2 get_leaf_terms
682 Title : get_leaf_terms
683 Usage : $engine->get_leaf_terms();
684 Function: Returns the leaf terms
685 Returns : Bio::Ontology::TermI
693 my @a = $self->graph()->sink_vertices();
695 return $self->get_terms( @a );
701 =head2 get_root_terms()
703 Title : get_root_terms
704 Usage : $engine->get_root_terms();
705 Function: Returns the root terms
706 Returns : Bio::Ontology::TermI
715 my @a = $self->graph()->source_vertices();
717 return $self->get_terms( @a );
725 Usage : @terms = $engine->get_terms( "GO:1234567", "GO:2234567" );
726 Function: Returns term objects with given identifiers
727 Returns : Bio::Ontology::TermI, or the term corresponding to the
728 first identifier if called in scalar context
734 my ( $self, @ids ) = @_;
738 foreach my $id ( @ids ) {
739 if ( $self->graph()->has_vertex( $id ) ) {
740 push( @terms, $self->graph()->get_vertex_attribute( $id, TERM
) ); # NG 05-02-16
744 return wantarray ?
@terms : shift(@terms);
751 Title : get_all_terms
752 Usage : $engine->get_all_terms();
753 Function: Returns all terms in this engine
754 Returns : Bio::Ontology::TermI
762 return( $self->get_terms( $self->graph()->vertices() ) );
770 Usage : ($term) = $oe->find_terms(-identifier => "SO:0000263");
771 Function: Find term instances matching queries for their attributes.
773 This implementation can efficiently resolve queries by
777 Returns : an array of zero or more Bio::Ontology::TermI objects
778 Args : Named parameters. The following parameters should be recognized
779 by any implementations:
781 -identifier query by the given identifier
782 -name query by the given name
787 my ($self,@args) = @_;
790 my ($id,$name) = $self->_rearrange([qw(IDENTIFIER NAME)],@args);
793 @terms = $self->get_terms($id);
795 @terms = $self->get_all_terms();
798 @terms = grep { $_->name() eq $name; } @terms;
804 =head2 find_identically_named_terms
806 Title : find_identically_named_terms
807 Usage : ($term) = $oe->find_identically_named_terms($term0);
808 Function: Find term instances where names match the query term
811 Returns : an array of zero or more Bio::Ontology::TermI objects
812 Args : a Bio::Ontology::TermI object
816 sub find_identically_named_terms
{
817 my ($self,$qterm) = @_;
818 $self->throw("Argument doesn't implement Bio::Ontology::TermI. " . "Bummer." )
819 unless defined $qterm and $qterm->isa("Bio::Ontology::TermI");
823 foreach my $term ($self->get_all_terms) {
824 $matching_terms{$term->identifier} = $term and next
825 if $term->name eq $qterm->name;
827 return values %matching_terms;
831 =head2 find_identical_terms
833 Title : find_identical_terms
834 Usage : ($term) = $oe->find_identical_terms($term0);
835 Function: Find term instances where name or synonym
836 matches the query exactly
838 Returns : an array of zero or more Bio::Ontology::TermI objects
839 Args : a Bio::Ontology::TermI object
843 sub find_identical_terms
{
844 my ($self,$qterm) = @_;
845 $self->throw("Argument doesn't implement Bio::Ontology::TermI. " . "Bummer." )
846 unless defined $qterm and $qterm->isa("Bio::Ontology::TermI");
850 foreach my $qstring ($qterm->name, $qterm->each_synonym) {
851 foreach my $term ($self->get_all_terms) {
852 foreach my $string ( $term->name, $term->each_synonym() ) {
853 $matching_terms{$term->identifier} = $term and next
854 if $string eq $qstring;
858 return values %matching_terms;
861 =head2 find_similar_terms
863 Title : find_similar_terms
864 Usage : ($term) = $oe->find_similar_terms($term0);
865 Function: Find term instances where name or synonym, or part of one,
868 Returns : an array of zero or more Bio::Ontology::TermI objects
869 Args : a Bio::Ontology::TermI object
873 sub find_similar_terms
{
874 my ($self,$qterm) = @_;
875 $self->throw("Argument doesn't implement Bio::Ontology::TermI. " . "Bummer." )
876 unless defined $qterm and $qterm->isa("Bio::Ontology::TermI");
880 foreach my $qstring ($qterm->name, $qterm->each_synonym) {
881 foreach my $term ($self->get_all_terms) {
883 foreach my $string ( $term->name, $term->each_synonym() ) {
884 $matching_terms{$term->identifier} = $term and next
885 if $string =~ /$qstring/ or $qstring =~ /$string/;
889 return values %matching_terms;
893 =head2 relationship_factory
895 Title : relationship_factory
896 Usage : $fact = $obj->relationship_factory()
897 Function: Get/set the object factory to be used when relationship
898 objects are created by the implementation on-the-fly.
901 Returns : value of relationship_factory (a Bio::Factory::ObjectFactoryI
903 Args : on set, a Bio::Factory::ObjectFactoryI compliant object
907 sub relationship_factory
{
910 return $self->{'relationship_factory'} = shift if @_;
911 return $self->{'relationship_factory'};
917 Usage : $fact = $obj->term_factory()
918 Function: Get/set the object factory to be used when term objects are
919 created by the implementation on-the-fly.
921 Note that this ontology engine implementation does not
922 create term objects on the fly, and therefore setting this
923 attribute is meaningless.
926 Returns : value of term_factory (a Bio::Factory::ObjectFactoryI
928 Args : on set, a Bio::Factory::ObjectFactoryI compliant object
936 $self->warn("setting term factory, but ".ref($self).
937 " does not create terms on-the-fly");
938 return $self->{'term_factory'} = shift;
940 return $self->{'term_factory'};
946 Usage : $engine->graph();
947 Function: Returns the Graph this engine is based on
954 my ( $self, $value ) = @_;
956 if ( defined $value ) {
957 $self->_check_class( $value, 'Bio::Ontology::SimpleGOEngine::GraphAdaptor' ); # NG 05-02-16
958 $self->{ "_graph" } = $value;
961 return $self->{ "_graph" };
967 # Checks the correct format of a GOBO-formatted id
968 # Gets the id out of a term or id string
970 my ( $self, $term ) = @_;
975 # use TermI standard API
977 "Object doesn't implement Bio::Ontology::TermI. " . "Bummer." )
978 unless $term->isa("Bio::Ontology::TermI");
979 $id = $term->identifier();
981 # if there is no ID, we need to fake one from ontology name and name
982 # in order to achieve uniqueness
984 $id = $term->ontology->name() if $term->ontology();
985 $id = $id ?
$id . '|' : '';
986 $id .= $term->name();
992 # if $term->isa("Bio::Ontology::GOterm")||($id =~ /^[A-Z_]{1,8}:\d{1,}$/);
993 if $term->isa("Bio::Ontology::OBOterm") || ( $id =~ /^\w+:\w+$/ );
995 # prefix with something if only numbers
996 # if($id =~ /^\d+$/) {
997 # $self->warn(ref($self).": identifier [$id] is only numbers - ".
998 # "prefixing with 'GO:'");
999 # return "GO:" . $id;
1001 # we shouldn't have gotten here if it's at least a remotely decent ID
1002 $self->throw( ref($self) . ": non-standard identifier '$id'\n" )
1007 # Helper for getting children and parent terms
1008 sub _get_child_parent_terms_helper
{
1009 my ( $self, $term, $do_get_child_terms, @types ) = @_;
1011 foreach my $type ( @types ) {
1012 $self->_check_class( $type, "Bio::Ontology::TermI" );
1015 my @relative_terms = ();
1017 $term = $self->_get_id( $term );
1018 if ( ! $self->graph()->has_vertex( $term ) ) {
1019 $self->throw( "Ontology does not contain a term with an identifier of \"$term\"" );
1022 my @all_relative_terms = ();
1023 if ( $do_get_child_terms ) {
1024 @all_relative_terms = $self->graph()->successors( $term );
1027 @all_relative_terms = $self->graph()->predecessors( $term );
1030 foreach my $relative ( @all_relative_terms ) {
1031 if ( scalar( @types ) > 0 ) {
1032 foreach my $type ( @types ) {
1034 if ( $do_get_child_terms ) {
1035 $relative_type = $self->graph()->get_edge_attribute ($term, $relative, TYPE
); # NG 05-02-16
1038 $relative_type = $self->graph()->get_edge_attribute ($relative, $term, TYPE
); # NG 05-02-16
1040 if ( $relative_type->equals( $type ) ) {
1041 push( @relative_terms, $relative );
1046 push( @relative_terms, $relative );
1050 return $self->get_terms( @relative_terms );
1056 sub _get_descendant_terms_helper
{
1057 my ( $self, $term, $ids_ref, $types_ref ) = @_;
1059 my @child_terms = $self->get_child_terms( $term, @
$types_ref );
1061 if ( scalar( @child_terms ) < 1 ) {
1065 foreach my $child_term ( @child_terms ) {
1066 my $child_term_id = $self->_get_id($child_term->identifier());
1067 $ids_ref->{ $child_term_id } = 0;
1068 $self->_get_descendant_terms_helper( $child_term_id, $ids_ref, $types_ref );
1071 } # _get_descendant_terms_helper
1075 sub _get_ancestor_terms_helper
{
1076 my ( $self, $term, $ids_ref, $types_ref ) = @_;
1078 my @parent_terms = $self->get_parent_terms( $term, @
$types_ref );
1080 if ( scalar( @parent_terms ) < 1 ) {
1084 foreach my $parent_term ( @parent_terms ) {
1085 my $parent_term_id = $self->_get_id($parent_term->identifier());
1086 $ids_ref->{ $parent_term_id } = 0;
1087 $self->_get_ancestor_terms_helper( $parent_term_id, $ids_ref, $types_ref );
1090 } # get_ancestor_terms_helper
1093 my ( $self, $value, $expected_class ) = @_;
1095 if ( ! defined( $value ) ) {
1096 $self->throw( "Found [undef] where [$expected_class] expected" );
1098 elsif ( ! ref( $value ) ) {
1099 $self->throw( "Found [scalar] where [$expected_class] expected" );
1101 elsif ( ! $value->isa( $expected_class ) ) {
1102 $self->throw( "Found [" . ref( $value ) . "] where [$expected_class] expected" );
1107 #################################################################
1109 #################################################################
1111 *get_relationship_types
= \
&get_predicate_terms
;