File Coverage

blib/lib/OBO/Core/Term.pm
Criterion Covered Total %
statement 233 246 94.7
branch 93 118 78.8
condition 42 66 63.6
subroutine 40 40 100.0
pod 31 32 96.8
total 439 502 87.4


line stmt bran cond sub pod time code
1             # $Id: Term.pm 2013-06-06 erick.antezana $
2             #
3             # Module : Term.pm
4             # Purpose : Term of an Ontology.
5             # License : Copyright (c) 2006-2014 by Erick Antezana. All rights reserved.
6             # This program is free software; you can redistribute it and/or
7             # modify it under the same terms as Perl itself.
8             # Contact : Erick Antezana
9             #
10             package OBO::Core::Term;
11              
12 12     12   9602 use OBO::Util::InstanceSet;
  12         23  
  12         298  
13 12     12   2577 use OBO::Core::Synonym;
  12         21  
  12         258  
14 12     12   2507 use OBO::Util::SynonymSet;
  12         18  
  12         244  
15              
16 12     12   50 use Carp;
  12         13  
  12         569  
17 12     12   54 use strict;
  12         12  
  12         266  
18 12     12   46 use warnings;
  12         13  
  12         34466  
19              
20             sub new {
21 2179     2179 0 2300 my $class = shift;
22 2179         2479 my $self = {};
23              
24 2179         3102 $self->{ID} = undef; # required, scalar (1)
25 2179         2391 $self->{IS_ANONYMOUS} = undef; # [1|0], 0 by default
26 2179         2449 $self->{NAME} = undef; # not required since OBO spec 1.4, scalar (0..1)
27 2179         5275 $self->{NAMESPACE_SET} = OBO::Util::Set->new(); # set (0..N)
28 2179         3858 $self->{ALT_ID} = OBO::Util::Set->new(); # set (0..N)
29 2179         2665 $self->{BUILTIN} = undef; # [1|0], 0 by default
30 2179         5626 $self->{DEF} = OBO::Core::Def->new(); # (0..1)
31 2179         3836 $self->{COMMENT} = undef; # scalar (0..1)
32 2179         3817 $self->{SUBSET_SET} = OBO::Util::Set->new(); # set of scalars (0..N)
33 2179         4723 $self->{SYNONYM_SET} = OBO::Util::SynonymSet->new(); # set of synonyms (0..N)
34 2179         4084 $self->{XREF_SET} = OBO::Util::DbxrefSet->new(); # set of dbxref's (0..N)
35 2179         4235 $self->{PROPERTY_VALUE} = OBO::Util::ObjectSet->new(); # set of objects: rel's Term->Instance or Term->Datatype (0..N)
36 2179         4655 $self->{CLASS_OF} = OBO::Util::InstanceSet->new();# set of instances (0..N)
37 2179         3938 $self->{INTERSECTION_OF} = OBO::Util::Set->new(); # (0..N) with N=0, 2, 3, ...
38 2179         3713 $self->{UNION_OF} = OBO::Util::Set->new(); # (0..N) with N=0, 2, 3, ...
39 2179         3548 $self->{DISJOINT_FROM} = OBO::Util::Set->new(); # (0..N)
40 2179         2901 $self->{CREATED_BY} = undef; # scalar (0..1)
41 2179         2371 $self->{CREATION_DATE} = undef; # scalar (0..1)
42 2179         2637 $self->{MODIFIED_BY} = undef; # scalar (0..1)
43 2179         1923 $self->{MODIFICATION_DATE} = undef; # scalar (0..1)
44 2179         2362 $self->{IS_OBSOLETE} = undef; # [1|0], 0 by default
45 2179         3464 $self->{REPLACED_BY} = OBO::Util::Set->new(); # set of scalars (0..N)
46 2179         3513 $self->{CONSIDER} = OBO::Util::Set->new(); # set of scalars (0..N)
47              
48 2179         2733 bless ($self, $class);
49 2179         3491 return $self;
50             }
51              
52             =head2 id
53              
54             Usage - print $term->id() or $term->id($id)
55             Returns - the term ID (string)
56             Args - the term ID (string)
57             Function - gets/sets the ID of this term
58            
59             =cut
60              
61             sub id {
62 227241 100   227241 1 298546 if ($_[1]) { $_[0]->{ID} = $_[1] }
  2181         3907  
63 227241         391624 return $_[0]->{ID};
64             }
65              
66             =head2 idspace
67              
68             Usage - print $term->idspace()
69             Returns - the idspace of this term; otherwise, 'NN'
70             Args - none
71             Function - gets the idspace of this term # TODO Does this method still makes sense?
72            
73             =cut
74              
75             sub idspace {
76 10 100   10 1 97 $_[0]->{ID} =~ /([A-Za-z_]+):/ if ($_[0]->{ID});
77 10   100     62 return $1 || 'NN';
78             }
79              
80             =head2 subnamespace
81              
82             Usage - print $term->subnamespace()
83             Returns - the subnamespace of this term (character); otherwise, 'X'
84             Args - none
85             Function - gets the subnamespace of this term
86            
87             =cut
88              
89             sub subnamespace {
90 2 100   2 1 11 $_[0]->{ID} =~ /:([A-Z][a-z]?)/ if ($_[0]->{ID});
91 2   100     12 return $1 || 'X';
92             }
93              
94             =head2 code
95              
96             Usage - print $term->code()
97             Returns - the code of this term (character); otherwise, '0000000'
98             Args - none
99             Function - gets the code of this term
100            
101             =cut
102              
103             sub code {
104 2 100   2 1 9 $_[0]->{ID} =~ /:[A-Z]?[a-z]?(.*)/ if ($_[0]->{ID});
105 2   100     15 return $1 || '0000000';
106             }
107              
108             =head2 name
109              
110             Usage - print $term->name() or $term->name($name)
111             Returns - the name (string) of this term
112             Args - the name (string) of this term
113             Function - gets/sets the name of this term
114            
115             =cut
116              
117             sub name {
118 15643 100   15643 1 24101 if ($_[1]) { $_[0]->{NAME} = $_[1] }
  2164         4258  
119 15643         36604 return $_[0]->{NAME};
120             }
121              
122             =head2 is_anonymous
123              
124             Usage - print $term->is_anonymous() or $term->is_anonymous("1")
125             Returns - either 1 (true) or 0 (false)
126             Args - either 1 (true) or 0 (false)
127             Function - tells whether this term is anonymous or not.
128            
129             =cut
130              
131             sub is_anonymous {
132 2756 50 66 2756 1 5025 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{IS_ANONYMOUS} = $_[1] }
  12   66     18  
133 2756 100 66     10534 return ($_[0]->{IS_ANONYMOUS} && $_[0]->{IS_ANONYMOUS} == 1)?1:0;
134             }
135              
136             =head2 alt_id
137              
138             Usage - $term->alt_id() or $term->alt_id($id1, $id2, $id3, ...)
139             Returns - a set (OBO::Util::Set) with the alternate id(s) of this term
140             Args - the alternate id(s) (string) of this term
141             Function - gets/sets the alternate id(s) of this term
142            
143             =cut
144              
145             sub alt_id {
146 3404     3404 1 3121 my $self = shift;
147 3404 100       7629 if (scalar(@_) > 1) {
    100          
148 1         6 $self->{ALT_ID}->add_all(@_);
149             } elsif (scalar(@_) == 1) {
150 11         37 $self->{ALT_ID}->add(shift);
151             }
152 3404         8458 return $self->{ALT_ID};
153             }
154              
155             =head2 def
156              
157             Usage - $term->def() or $term->def($def)
158             Returns - the definition (OBO::Core::Def) of this term
159             Args - the definition (OBO::Core::Def) of this term
160             Function - gets/sets the definition of the term
161            
162             =cut
163              
164             sub def {
165 7746 100   7746 1 12195 $_[0]->{DEF} = $_[1] if ($_[1]);
166 7746         22216 return $_[0]->{DEF};
167             }
168              
169             =head2 def_as_string
170              
171             Usage - $term->def_as_string() or $term->def_as_string("During meiosis, the synthesis of DNA proceeding from the broken 3' single-strand DNA end that uses the homologous intact duplex as the template.", "[GOC:elh, PMID:9334324]")
172             Returns - the definition (string) of this term
173             Args - the definition (string) of this term plus the dbxref list (string) describing the source of this definition
174             Function - gets/sets the definition of this term
175             Remark - make sure that colons (,) are scaped (\,) when necessary
176            
177             =cut
178              
179             sub def_as_string {
180 544     544 1 476 my $dbxref_as_string = $_[2];
181 544 100 66     1046 if (defined $_[1] && defined $dbxref_as_string) {
182 8         16 my $def = $_[0]->{DEF};
183 8         27 $def->text($_[1]);
184 8         20 my $dbxref_set = OBO::Util::DbxrefSet->new();
185            
186 8         20 my ($e, $entry) = __dbxref($dbxref_set, $dbxref_as_string);
187 8 50       21 if ($e == -1) {
188 0         0 croak "ERROR: Check the 'dbxref' field of '", $entry, "' (term ID = ", $_[0]->id(), ")." ;
189             }
190            
191 8         21 $def->dbxref_set($dbxref_set);
192             }
193            
194 470         776 my @sorted_dbxrefs = map { $_->[0] } # restore original values
  113         242  
195 470         913 sort { $a->[1] cmp $b->[1] } # sort
196 544         1306 map { [$_, lc($_->id())] } # transform: value, sortkey
197             $_[0]->{DEF}->dbxref_set()->get_set();
198              
199 544         907 my @result = (); # a Set?
200 544         663 foreach my $dbxref (@sorted_dbxrefs) {
201 470         953 push @result, $dbxref->as_string();
202             }
203 544         1363 my $d = $_[0]->{DEF}->text();
204 544 100       933 if (defined $d) {
205 539         1201 return '"'.$_[0]->{DEF}->text().'"'.' ['.join(', ', @result).']';
206             } else {
207 5         22 return '"" ['.join(', ', @result).']';
208             }
209             }
210              
211             =head2 namespace
212              
213             Usage - $term->namespace() or $term->namespace($ns1, $ns2, $ns3, ...)
214             Returns - an array with the namespace(s) to which this term belongs
215             Args - the namespace(s) to which this term belongs
216             Function - gets/sets the namespace(s) to which this term belongs
217            
218             =cut
219              
220             sub namespace {
221 2115     2115 1 2277 my $self = shift;
222 2115 50       5148 if (scalar(@_) > 1) {
    100          
223 0         0 $self->{NAMESPACE_SET}->add_all(@_);
224             } elsif (scalar(@_) == 1) {
225 14         48 $self->{NAMESPACE_SET}->add(shift);
226             }
227 2115         5556 return $self->{NAMESPACE_SET}->get_set();
228             }
229              
230             =head2 comment
231              
232             Usage - print $term->comment() or $term->comment("This is a comment")
233             Returns - the comment (string) of this term
234             Args - the comment (string) of this term
235             Function - gets/sets the comment of this term
236            
237             =cut
238              
239             sub comment {
240 3981 100   3981 1 6484 if (defined $_[1]) { $_[0]->{COMMENT} = $_[1] }
  193         419  
241 3981         10371 return $_[0]->{COMMENT};
242             }
243              
244             =head2 subset
245              
246             Usage - $term->subset() or $term->subset($ss_name1, $ss_name2, $ss_name3, ...)
247             Returns - an array with the subset name(s) to which this term belongs
248             Args - the subset name(s) (string) to which this term belongs
249             Function - gets/sets the subset name(s) to which this term belongs
250            
251             =cut
252              
253             sub subset {
254 3436     3436 1 3202 my $self = shift;
255 3436 100       7480 if (scalar(@_) > 1) {
    100          
256 1         5 $self->{SUBSET_SET}->add_all(@_);
257             } elsif (scalar(@_) == 1) {
258 37         123 $self->{SUBSET_SET}->add(shift);
259             }
260 3436         8392 return $self->{SUBSET_SET}->get_set();
261             }
262              
263             =head2 synonym_set
264              
265             Usage - $term->synonym_set() or $term->synonym_set($synonym1, $synonym2, $synonym3, ...)
266             Returns - an array with the synonym(s) of this term
267             Args - the synonym(s) (OBO::Core::Synonym) of this term
268             Function - gets/sets the synonym(s) of this term
269             Remark1 - if the synonym (text) is already in the set of synonyms of this term, its scope (and their dbxref's) will be updated (provided they have the same synonym type name)
270             Remark2 - a synonym text identical to the term name is not added to the set of synonyms of this term
271            
272             =cut
273              
274             sub synonym_set {
275 5544     5544 1 5090 my $self = shift;
276 5544         6126 foreach my $synonym (@_) {
277 2122         2966 my $term_name = $self->name();
278 2122 50       3467 if (!defined($term_name)) {
279 0         0 croak 'The name of this term (', $self->id(), ') is undefined. Add it before adding its synonyms.';
280             }
281            
282             #
283             # update the scope (and dbxref's) of a synonym -- if the text and synonym type name are identical in both synonyms
284             #
285 2122         2128 my $syn_found = 0;
286 2122         4375 foreach my $s ($self->{SYNONYM_SET}->get_set()) {
287            
288 3700 100       5524 if ($s->def()->text() eq $synonym->def()->text()) { # if that SYNONYM is already in the set
289            
290 9         18 my $synonym_type_name = $synonym->synonym_type_name();
291 9         15 my $s_type_name = $s->synonym_type_name();
292 9 100 66     24 if ($synonym_type_name || $s_type_name) { # if any of their STN's is defined
293 6 100 66     35 if ($s_type_name && $synonym_type_name && ($s_type_name eq $synonym_type_name)) { # they should be identical
      100        
294            
295 1         2 $s->def()->dbxref_set($synonym->def()->dbxref_set); # then update its DBXREFs!
296 1         3 $s->scope($synonym->scope); # then update its SCOPE!
297            
298 1         1 $syn_found = 1;
299 1         3 last;
300             }
301             } else {
302 3         4 $s->def()->dbxref_set($synonym->def()->dbxref_set); # then update its DBXREFs!
303 3         6 $s->scope($synonym->scope); # then update its SCOPE!
304            
305 3         3 $syn_found = 1;
306 3         3 last;
307             }
308             }
309             }
310            
311             # do not add 'EXACT' synonyms with the same 'name':
312 2122 50 66     6732 if (!$syn_found && !($synonym->scope() eq 'EXACT' && $synonym->def()->text() eq $term_name)) {
      66        
313 2118 50       3772 $self->{SYNONYM_SET}->add($synonym) || warn "ERROR: the synonym (", $synonym->def()->text(), ") was not added!!";
314             }
315             }
316 5544         11563 return $self->{SYNONYM_SET}->get_set();
317             }
318              
319             =head2 synonym_as_string
320              
321             Usage - print $term->synonym_as_string() or $term->synonym_as_string('this is a synonym text', '[APO:ea]', 'EXACT', 'UK_SPELLING')
322             Returns - an array with the synonym(s) of this term
323             Args - the synonym text (string), the dbxrefs (string), synonym scope (string) of this term, and optionally the synonym type name (string)
324             Function - gets/sets the synonym(s) of this term
325             Remark1 - if the synonym (text) is already in the set of synonyms of this term, its scope (and their dbxref's) will be updated (provided they have the same synonym type name)
326             Remark2 - a synonym text identical to the term name is not added to the set of synonyms of this term
327            
328             =cut
329              
330             sub synonym_as_string {
331 2135 50 66 2135 1 9045 if ($_[1] && $_[2] && $_[3]) {
      33        
332 2119         4834 my $synonym = OBO::Core::Synonym->new();
333 2119         4666 $synonym->def_as_string($_[1], $_[2]);
334 2119         5119 $synonym->scope($_[3]);
335 2119         4127 $synonym->synonym_type_name($_[4]); # optional argument
336 2119         4108 $_[0]->synonym_set($synonym);
337             }
338            
339 5859         7740 my @sorted_syns = map { $_->[0] } # restore original values
  6133         7013  
340 5859         9623 sort { $a->[1] cmp $b->[1] } # sort
341 2135         4998 map { [$_, lc($_->def_as_string())] } # transform: value, sortkey
342             $_[0]->{SYNONYM_SET}->get_set();
343              
344 2135         3574 my @result;
345             my $s_as_string;
346 2135         2381 foreach my $synonym (@sorted_syns) {
347 5859         9192 my $syn_scope = $synonym->scope();
348 5859 50       6673 if ($syn_scope) {
349 5859         8345 my $syn_type_name = $synonym->synonym_type_name();
350 5859 100       6503 if ($syn_type_name) {
351 26         48 $s_as_string = ' '.$syn_scope.' '.$syn_type_name;
352             } else {
353 5833         6121 $s_as_string = ' '.$syn_scope;
354             }
355             } else {
356             # This case should never happen since the SCOPE is mandatory!
357 0         0 warn "The scope of this synonym is not defined: ", $synonym->def()->text();
358             }
359            
360 5859         8689 push @result, $synonym->def_as_string().$s_as_string;
361             }
362 2135         7122 return @result;
363             }
364              
365             =head2 xref_set
366              
367             Usage - $term->xref_set() or $term->xref_set($dbxref_set)
368             Returns - a Dbxref set (OBO::Util::DbxrefSet) with the analogous xref(s) of this term in another vocabulary
369             Args - a set of analogous xref(s) (OBO::Util::DbxrefSet) of this term in another vocabulary
370             Function - gets/sets the analogous xref(s) set of this term in another vocabulary
371            
372             =cut
373              
374             sub xref_set {
375 4573 100   4573 1 6560 $_[0]->{XREF_SET} = $_[1] if ($_[1]);
376 4573         10373 return $_[0]->{XREF_SET};
377             }
378              
379             =head2 xref_set_as_string
380              
381             Usage - $term->xref_set_as_string() or $term->xref_set_as_string("[Reactome:20610, EC:2.3.2.12]")
382             Returns - the dbxref set with the analogous xref(s) of this term; [] if the set is empty
383             Args - the dbxref set with the analogous xref(s) of this term
384             Function - gets/sets the dbxref set with the analogous xref(s) of this term
385             Remark - make sure that colons (,) are scaped (\,) when necessary
386            
387             =cut
388              
389             sub xref_set_as_string {
390 3869     3869 1 5240 my $xref_as_string = $_[1];
391 3869 100       5788 if ($xref_as_string) {
392 1170         1774 my $xref_set = $_[0]->{XREF_SET};
393            
394 1170         2011 my ($e, $entry) = __dbxref($xref_set, $xref_as_string);
395 1170 50       2348 if ($e == -1) {
396 0         0 croak "ERROR: Check the 'dbxref' field of '", $entry, "' (term ID = ", $_[0]->id(), ")." ;
397             }
398              
399 1170         1659 $_[0]->{XREF_SET} = $xref_set; # We are overwriting the existing set; otherwise, add the new elements to the existing set!
400             }
401 3869         6764 my @result = $_[0]->xref_set()->get_set();
402             }
403              
404             =head2 property_value
405              
406             Usage - $term->property_value() or $term->property_value($p_value1, $p_value2, $p_value3, ...)
407             Returns - an array with the property value(s) of this term
408             Args - the relationship(s) (OBO::Core::Relationship) of this term with its property value(s)
409             Function - gets/sets the property_value(s) of this term
410             Remark - WARNING: this code might change!
411            
412             =cut
413              
414             sub property_value {
415             # TODO WARNING: this code might change!
416 2700     2700 1 3577 my ($self, @co) = @_;
417            
418 2700         2984 foreach my $i (@co) {
419 7         16 $self->{PROPERTY_VALUE}->add($i);
420             }
421 2700         8703 return $self->{PROPERTY_VALUE};
422             }
423              
424             =head2 class_of
425              
426             Usage - $term->class_of() or $term->class_of($instance1, $instance2, $instance3, ...)
427             Returns - an array with the instance(s) of this term
428             Args - the instance(s) (OBO::Core::Instance) of this term
429             Function - gets/sets the instance(s) of this term
430            
431             =cut
432              
433             sub class_of {
434 123     123 1 150 my ($self, @co) = @_;
435            
436 123         154 foreach my $i (@co) {
437 4         14 $self->{CLASS_OF}->add($i);
438 4         9 $i->instance_of($self); # make the instance aware of its class (term)
439             }
440 123         352 return $self->{CLASS_OF};
441             }
442              
443             =head2 is_class_of
444              
445             Usage - $term->is_class_of($instance)
446             Returns - either 1 (true) or 0 (false)
447             Args - an instance (OBO::Core::Instance) of which this object might be class of
448             Function - tells whether this object is a class of $instance
449            
450             =cut
451              
452             sub is_class_of {
453 12   66 12 1 82 return (defined $_[1] && $_[0]->{CLASS_OF}->contains($_[1]));
454             }
455              
456             =head2 intersection_of
457              
458             Usage - $term->intersection_of() or $term->intersection_of($t1, $t2, $r1, ...)
459             Returns - an array with the terms/relations which define this term
460             Args - a set (strings) of terms/relations which define this term
461             Function - gets/sets the set of terms/relationships defining this term
462              
463             =cut
464              
465             sub intersection_of {
466 3389     3389 1 3515 my $self = shift;
467 3389 50       8035 if (scalar(@_) > 1) {
    100          
468 0         0 $self->{INTERSECTION_OF}->add_all(@_);
469             } elsif (scalar(@_) == 1) {
470 4         10 $self->{INTERSECTION_OF}->add(shift);
471             }
472 3389         8907 return $self->{INTERSECTION_OF}->get_set();
473             }
474              
475             =head2 union_of
476            
477             Usage - $term->union_of() or $term->union_of($t1, $t2, $r1, ...)
478             Returns - an array with the terms/relations which define this term
479             Args - a set (strings) of terms/relations which define this term
480             Function - gets/sets the set of terms/relationships defining this term
481              
482             =cut
483            
484             sub union_of {
485 3387     3387 1 2803 my $self = shift;
486 3387 50       8038 if (scalar(@_) > 1) {
    100          
487 0         0 $self->{UNION_OF}->add_all(@_);
488             } elsif (scalar(@_) == 1) {
489 2         6 $self->{UNION_OF}->add(shift);
490             }
491 3387         6298 return $self->{UNION_OF}->get_set();
492             }
493              
494             =head2 disjoint_from
495              
496             Usage - $term->disjoint_from() or $term->disjoint_from($disjoint_term_id1, $disjoint_term_id2, $disjoint_term_id3, ...)
497             Returns - the disjoint term id(s) (string(s)) from this one
498             Args - the term id(s) (string) that is (are) disjoint from this one
499             Function - gets/sets the disjoint term(s) from this one
500              
501             =cut
502              
503             sub disjoint_from {
504 3402     3402 1 3545 my $self = shift;
505 3402 100       7401 if (scalar(@_) > 1) {
    100          
506 1         6 $self->{DISJOINT_FROM}->add_all(@_);
507             } elsif (scalar(@_) == 1) {
508 15         57 $self->{DISJOINT_FROM}->add(shift);
509             }
510 3402         6780 return $self->{DISJOINT_FROM}->get_set();
511             }
512              
513             =head2 created_by
514              
515             Usage - print $term->created_by() or $term->created_by("erick_antezana")
516             Returns - name (string) of the creator of the term, may be a short username, initials or ID
517             Args - name (string) of the creator of the term, may be a short username, initials or ID
518             Function - gets/sets the name of the creator of the term
519            
520             =cut
521              
522             sub created_by {
523 2716 100   2716 1 4509 $_[0]->{CREATED_BY} = $_[1] if ($_[1]);
524 2716         7689 return $_[0]->{CREATED_BY};
525             }
526              
527             =head2 creation_date
528              
529             Usage - print $term->creation_date() or $term->creation_date("2010-04-13T01:32:36Z")
530             Returns - date (string) of creation of the term specified in ISO 8601 format
531             Args - date (string) of creation of the term specified in ISO 8601 format
532             Function - gets/sets the date of creation of the term
533             Remark - You can get an ISO 8601 date as follows:
534             use POSIX qw(strftime);
535             my $datetime = strftime("%Y-%m-%dT%H:%M:%S", localtime());
536              
537             =cut
538              
539             sub creation_date {
540 2718 100   2718 1 4411 $_[0]->{CREATION_DATE} = $_[1] if ($_[1]);
541 2718         6075 return $_[0]->{CREATION_DATE};
542             }
543              
544             =head2 modified_by
545              
546             Usage - print $term->modified_by() or $term->modified_by("erick_antezana")
547             Returns - name (string) of the modificator of the term, may be a short username, initials or ID
548             Args - name (string) of the modificator of the term, may be a short username, initials or ID
549             Function - gets/sets the name of the modificator of the term
550            
551             =cut
552              
553             sub modified_by {
554             # TODO WARNING: This is not going to be in the OBO spec. Use property_values instead...
555 2693 100   2693 1 3993 $_[0]->{MODIFIED_BY} = $_[1] if ($_[1]);
556 2693         5654 return $_[0]->{MODIFIED_BY};
557             }
558              
559             =head2 modification_date
560              
561             Usage - print $term->modification_date() or $term->modification_date("2010-04-13T01:32:36Z")
562             Returns - date (string) of modification of the term specified in ISO 8601 format
563             Args - date (string) of modification of the term specified in ISO 8601 format
564             Function - gets/sets the date of modification of the term
565             Remark - You can get an ISO 8601 date as follows:
566             use POSIX qw(strftime);
567             my $datetime = strftime("%Y-%m-%dT%H:%M:%S", localtime());
568            
569             =cut
570              
571             sub modification_date {
572             # TODO WARNING: This is not going to be in the OBO spec. Use property_values instead...
573 2693 100   2693 1 3688 $_[0]->{MODIFICATION_DATE} = $_[1] if ($_[1]);
574 2693         5930 return $_[0]->{MODIFICATION_DATE};
575             }
576              
577             =head2 is_obsolete
578              
579             Usage - $term->is_obsolete(1) or print $term->is_obsolete()
580             Returns - either 1 (true) or 0 (false)
581             Args - either 1 (true) or 0 (false)
582             Function - tells whether the term is obsolete or not. 'false' by default.
583            
584             =cut
585              
586             sub is_obsolete {
587 3421 50 66 3421 1 5556 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{IS_OBSOLETE} = $_[1] }
  31   66     58  
588 3421 100 66     13192 return ($_[0]->{IS_OBSOLETE} && $_[0]->{IS_OBSOLETE} == 1)?1:0;
589             }
590              
591             =head2 replaced_by
592              
593             Usage - $term->replaced_by() or $term->replaced_by($id1, $id2, $id3, ...)
594             Returns - a set (OBO::Util::Set) with the id(s) of the replacing term(s)
595             Args - the the id(s) of the replacing term(s) (string)
596             Function - gets/sets the the id(s) of the replacing term(s)
597            
598             =cut
599              
600             sub replaced_by {
601 3385     3385 1 3648 my $self = shift;
602 3385 50       7874 if (scalar(@_) > 1) {
    50          
603 0         0 $self->{REPLACED_BY}->add_all(@_);
604             } elsif (scalar(@_) == 1) {
605 0         0 $self->{REPLACED_BY}->add(shift);
606             }
607 3385         9637 return $self->{REPLACED_BY};
608             }
609              
610             =head2 consider
611              
612             Usage - $term->consider() or $term->consider($id1, $id2, $id3, ...)
613             Returns - a set (OBO::Util::Set) with the appropiate substitute(s) for an obsolete term
614             Args - the appropiate substitute(s) for an obsolete term (string)
615             Function - gets/sets the appropiate substitute(s) for this obsolete term
616            
617             =cut
618              
619             sub consider {
620 3385     3385 1 2881 my $self = shift;
621 3385 50       7199 if (scalar(@_) > 1) {
    50          
622 0         0 $self->{CONSIDER}->add_all(@_);
623             } elsif (scalar(@_) == 1) {
624 0         0 $self->{CONSIDER}->add(shift);
625             }
626 3385         6232 return $self->{CONSIDER};
627             }
628              
629             =head2 builtin
630              
631             Usage - $term->builtin() or $term->builtin(1) or $term->builtin(0)
632             Returns - tells if this term is builtin to the OBO format; false by default
633             Args - 1 (true) or 0 (false)
634             Function - gets/sets the value indicating whether this term is builtin to the OBO format
635            
636             =cut
637              
638             sub builtin {
639 2746 50 33 2746 1 4334 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{BUILTIN} = $_[1] }
  8   66     11  
640 2746 50 33     9851 return ($_[0]->{BUILTIN} && $_[0]->{BUILTIN} == 1)?1:0;
641             }
642              
643             =head2 equals
644              
645             Usage - print $term->equals($another_term)
646             Returns - either 1 (true) or 0 (false)
647             Args - the term (OBO::Core::Term) to compare with
648             Function - tells whether this term is equal to the parameter
649            
650             =cut
651              
652             sub equals {
653 34 50 33 34 1 93 if ($_[1] && eval { $_[1]->isa('OBO::Core::Term') }) {
  34         149  
654 34 50 33     205 return (defined $_[1] && $_[0]->{'ID'} eq $_[1]->{'ID'})?1:0;
655             } else {
656 0         0 croak "An unrecognized object type (not a OBO::Core::Term) was found: '", $_[1], "'";
657             }
658             }
659              
660             sub __dbxref () {
661 1178 50   1178   2238 caller eq __PACKAGE__ or croak "You cannot call this (__dbxref) prived method!";
662             #
663             # $_[0] ==> set
664             # $_[1] ==> dbxref string
665             #
666 1178         1104 my $dbxref_set = $_[0];
667 1178         1184 my $dbxref_as_string = $_[1];
668            
669 1178         1473 $dbxref_as_string =~ s/^\[//;
670 1178         1408 $dbxref_as_string =~ s/\]$//;
671 1178         1206 $dbxref_as_string =~ s/\\,/;;;;/g; # trick to keep the comma's
672 1178         1042 $dbxref_as_string =~ s/\\"/;;;;;/g; # trick to keep the double quote's
673            
674 1178         1941 my @lineas = $dbxref_as_string =~ /\"([^\"]*)\"/g; # get the double-quoted pieces
675 1178         1589 foreach my $l (@lineas) {
676 8         10 my $cp = $l;
677 8         11 $l =~ s/,/;;;;/g; # trick to keep the comma's
678 8         113 $dbxref_as_string =~ s/\Q$cp\E/$l/;
679             }
680              
681 1178         3221 my $r_db_acc = qr/([ \*\.\w-]*):([ ;'\#~\w:\\\+\?\{\}\$\/\(\)\[\]\.=&!%_-]*)/o;
682 1178         1904 my $r_desc = qr/\s+\"([^\"]*)\"/o;
683 1178         1851 my $r_mod = qr/\s+(\{[\w ]+=[\w ]+\})/o;
684            
685 1178         2811 my @dbxrefs = split (',', $dbxref_as_string);
686              
687 1178         1329 foreach my $entry (@dbxrefs) {
688 1186         1341 my ($match, $db, $acc, $desc, $mod) = undef;
689 1186         3239 my $dbxref = OBO::Core::Dbxref->new();
690 1186 100       24776 if ($entry =~ m/$r_db_acc$r_desc$r_mod?/) {
    50          
691 8         17 $db = __unescape($1);
692 8         17 $acc = __unescape($2);
693 8         11 $desc = __unescape($3);
694 8 100       24 $mod = __unescape($4) if ($4);
695             } elsif ($entry =~ m/$r_db_acc$r_desc?$r_mod?/) {
696 1178         1919 $db = __unescape($1);
697 1178         1764 $acc = __unescape($2);
698 1178 50       2579 $desc = __unescape($3) if ($3);
699 1178 50       2262 $mod = __unescape($4) if ($4);
700             } else {
701 0         0 return (-1, $entry);
702             }
703            
704             # set the dbxref:
705 1186         3802 $dbxref->name($db.':'.$acc);
706 1186 100       2073 $dbxref->description($desc) if (defined $desc);
707 1186 100       1802 $dbxref->modifier($mod) if (defined $mod);
708 1186         2506 $dbxref_set->add($dbxref);
709             }
710 1178         3410 return 1;
711             }
712              
713             sub __unescape {
714 2383 50   2383   3935 caller eq __PACKAGE__ or die;
715 2383         2920 my $match = $_[0];
716 2383         2160 $match =~ s/;;;;;/\\"/g;
717 2383         1964 $match =~ s/;;;;/\\,/g;
718 2383         3260 return $match;
719             }
720              
721             1;
722              
723             __END__