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-2015 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   14314 use OBO::Util::InstanceSet;
  12         24  
  12         372  
13 12     12   3779 use OBO::Core::Synonym;
  12         26  
  12         316  
14 12     12   3937 use OBO::Util::SynonymSet;
  12         27  
  12         275  
15              
16 12     12   60 use Carp;
  12         24  
  12         668  
17 12     12   59 use strict;
  12         24  
  12         227  
18 12     12   56 use warnings;
  12         21  
  12         47566  
19              
20             sub new {
21 2180     2180 0 3358 my $class = shift;
22 2180         3277 my $self = {};
23              
24 2180         4684 $self->{ID} = undef; # required, scalar (1)
25 2180         3340 $self->{IS_ANONYMOUS} = undef; # [1|0], 0 by default
26 2180         3542 $self->{NAME} = undef; # not required since OBO spec 1.4, scalar (0..1)
27 2180         6177 $self->{NAMESPACE_SET} = OBO::Util::Set->new(); # set (0..N)
28 2180         5502 $self->{ALT_ID} = OBO::Util::Set->new(); # set (0..N)
29 2180         3517 $self->{BUILTIN} = undef; # [1|0], 0 by default
30 2180         6081 $self->{DEF} = OBO::Core::Def->new(); # (0..1)
31 2180         5169 $self->{COMMENT} = undef; # scalar (0..1)
32 2180         5560 $self->{SUBSET_SET} = OBO::Util::Set->new(); # set of scalars (0..N)
33 2180         5993 $self->{SYNONYM_SET} = OBO::Util::SynonymSet->new(); # set of synonyms (0..N)
34 2180         5930 $self->{XREF_SET} = OBO::Util::DbxrefSet->new(); # set of dbxref's (0..N)
35 2180         5709 $self->{PROPERTY_VALUE} = OBO::Util::ObjectSet->new(); # set of objects: rel's Term->Instance or Term->Datatype (0..N)
36 2180         5945 $self->{CLASS_OF} = OBO::Util::InstanceSet->new();# set of instances (0..N)
37 2180         5865 $self->{INTERSECTION_OF} = OBO::Util::Set->new(); # (0..N) with N=0, 2, 3, ...
38 2180         5546 $self->{UNION_OF} = OBO::Util::Set->new(); # (0..N) with N=0, 2, 3, ...
39 2180         5401 $self->{DISJOINT_FROM} = OBO::Util::Set->new(); # (0..N)
40 2180         3438 $self->{CREATED_BY} = undef; # scalar (0..1)
41 2180         3683 $self->{CREATION_DATE} = undef; # scalar (0..1)
42 2180         3467 $self->{MODIFIED_BY} = undef; # scalar (0..1)
43 2180         3063 $self->{MODIFICATION_DATE} = undef; # scalar (0..1)
44 2180         2930 $self->{IS_OBSOLETE} = undef; # [1|0], 0 by default
45 2180         5559 $self->{REPLACED_BY} = OBO::Util::Set->new(); # set of scalars (0..N)
46 2180         6070 $self->{CONSIDER} = OBO::Util::Set->new(); # set of scalars (0..N)
47              
48 2180         3244 bless ($self, $class);
49 2180         4632 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 227259 100   227259 1 445936 if ($_[1]) { $_[0]->{ID} = $_[1] }
  2182         4554  
63 227259         657970 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 121 $_[0]->{ID} =~ /([A-Za-z_]+):/ if ($_[0]->{ID});
77 10   100     94 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     15 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     13 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 15650 100   15650 1 31538 if ($_[1]) { $_[0]->{NAME} = $_[1] }
  2165         4680  
119 15650         50777 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 6492 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{IS_ANONYMOUS} = $_[1] }
  12   66     25  
133 2756 100 66     13618 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 4647 my $self = shift;
147 3404 100       9173 if (scalar(@_) > 1) {
    100          
148 1         6 $self->{ALT_ID}->add_all(@_);
149             } elsif (scalar(@_) == 1) {
150 11         46 $self->{ALT_ID}->add(shift);
151             }
152 3404         11458 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 7747 100   7747 1 16208 $_[0]->{DEF} = $_[1] if ($_[1]);
166 7747         25979 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 700 my $dbxref_as_string = $_[2];
181 544 100 66     1345 if (defined $_[1] && defined $dbxref_as_string) {
182 8         17 my $def = $_[0]->{DEF};
183 8         33 $def->text($_[1]);
184 8         33 my $dbxref_set = OBO::Util::DbxrefSet->new();
185            
186 8         30 my ($e, $entry) = __dbxref($dbxref_set, $dbxref_as_string);
187 8 50       26 if ($e == -1) {
188 0         0 croak "ERROR: Check the 'dbxref' field of '", $entry, "' (term ID = ", $_[0]->id(), ")." ;
189             }
190            
191 8         38 $def->dbxref_set($dbxref_set);
192             }
193            
194 470         1001 my @sorted_dbxrefs = map { $_->[0] } # restore original values
195 113         230 sort { $a->[1] cmp $b->[1] } # sort
196 470         1192 map { [$_, lc($_->id())] } # transform: value, sortkey
197 544         1523 $_[0]->{DEF}->dbxref_set()->get_set();
198              
199 544         1124 my @result = (); # a Set?
200 544         852 foreach my $dbxref (@sorted_dbxrefs) {
201 470         1298 push @result, $dbxref->as_string();
202             }
203 544         1649 my $d = $_[0]->{DEF}->text();
204 544 100       1160 if (defined $d) {
205 539         1465 return '"'.$_[0]->{DEF}->text().'"'.' ['.join(', ', @result).']';
206             } else {
207 5         31 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 2116     2116 1 2919 my $self = shift;
222 2116 50       6113 if (scalar(@_) > 1) {
    100          
223 0         0 $self->{NAMESPACE_SET}->add_all(@_);
224             } elsif (scalar(@_) == 1) {
225 15         50 $self->{NAMESPACE_SET}->add(shift);
226             }
227 2116         7181 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 3982 100   3982 1 8101 if (defined $_[1]) { $_[0]->{COMMENT} = $_[1] }
  194         448  
241 3982         12452 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 4591 my $self = shift;
255 3436 100       9454 if (scalar(@_) > 1) {
    100          
256 1         4 $self->{SUBSET_SET}->add_all(@_);
257             } elsif (scalar(@_) == 1) {
258 37         124 $self->{SUBSET_SET}->add(shift);
259             }
260 3436         10878 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 5550     5550 1 7288 my $self = shift;
276 5550         8888 foreach my $synonym (@_) {
277 2128         4270 my $term_name = $self->name();
278 2128 50       4948 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 2128         2440 my $syn_found = 0;
286 2128         6017 foreach my $s ($self->{SYNONYM_SET}->get_set()) {
287            
288 3715 100       9009 if ($s->def()->text() eq $synonym->def()->text()) { # if that SYNONYM is already in the set
289            
290 9         26 my $synonym_type_name = $synonym->synonym_type_name();
291 9         25 my $s_type_name = $s->synonym_type_name();
292 9 100 66     34 if ($synonym_type_name || $s_type_name) { # if any of their STN's is defined
293 6 100 66     50 if ($s_type_name && $synonym_type_name && ($s_type_name eq $synonym_type_name)) { # they should be identical
      100        
294            
295 1         5 $s->def()->dbxref_set($synonym->def()->dbxref_set); # then update its DBXREFs!
296 1         4 $s->scope($synonym->scope); # then update its SCOPE!
297            
298 1         2 $syn_found = 1;
299 1         2 last;
300             }
301             } else {
302 3         10 $s->def()->dbxref_set($synonym->def()->dbxref_set); # then update its DBXREFs!
303 3         10 $s->scope($synonym->scope); # then update its SCOPE!
304            
305 3         4 $syn_found = 1;
306 3         6 last;
307             }
308             }
309             }
310            
311             # do not add 'EXACT' synonyms with the same 'name':
312 2128 50 66     8887 if (!$syn_found && !($synonym->scope() eq 'EXACT' && $synonym->def()->text() eq $term_name)) {
      66        
313 2124 50       5644 $self->{SYNONYM_SET}->add($synonym) || warn "ERROR: the synonym (", $synonym->def()->text(), ") was not added!!";
314             }
315             }
316 5550         16759 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 2141 50 66 2141 1 12531 if ($_[1] && $_[2] && $_[3]) {
      33        
332 2125         6336 my $synonym = OBO::Core::Synonym->new();
333 2125         5952 $synonym->def_as_string($_[1], $_[2]);
334 2125         7425 $synonym->scope($_[3]);
335 2125         5853 $synonym->synonym_type_name($_[4]); # optional argument
336 2125         4950 $_[0]->synonym_set($synonym);
337             }
338            
339 5880         11392 my @sorted_syns = map { $_->[0] } # restore original values
340 6158         9499 sort { $a->[1] cmp $b->[1] } # sort
341 5880         15294 map { [$_, lc($_->def_as_string())] } # transform: value, sortkey
342 2141         7185 $_[0]->{SYNONYM_SET}->get_set();
343              
344 2141         5891 my @result;
345             my $s_as_string;
346 2141         3449 foreach my $synonym (@sorted_syns) {
347 5880         14765 my $syn_scope = $synonym->scope();
348 5880 50       11370 if ($syn_scope) {
349 5880         13929 my $syn_type_name = $synonym->synonym_type_name();
350 5880 100       9662 if ($syn_type_name) {
351 26         66 $s_as_string = ' '.$syn_scope.' '.$syn_type_name;
352             } else {
353 5854         9360 $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 5880         13934 push @result, $synonym->def_as_string().$s_as_string;
361             }
362 2141         8569 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 4580 100   4580 1 8811 $_[0]->{XREF_SET} = $_[1] if ($_[1]);
376 4580         14367 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 3876     3876 1 6368 my $xref_as_string = $_[1];
391 3876 100       7748 if ($xref_as_string) {
392 1176         1933 my $xref_set = $_[0]->{XREF_SET};
393            
394 1176         2272 my ($e, $entry) = __dbxref($xref_set, $xref_as_string);
395 1176 50       2663 if ($e == -1) {
396 0         0 croak "ERROR: Check the 'dbxref' field of '", $entry, "' (term ID = ", $_[0]->id(), ")." ;
397             }
398              
399 1176         2261 $_[0]->{XREF_SET} = $xref_set; # We are overwriting the existing set; otherwise, add the new elements to the existing set!
400             }
401 3876         8398 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 4614 my ($self, @co) = @_;
417            
418 2700         4324 foreach my $i (@co) {
419 7         24 $self->{PROPERTY_VALUE}->add($i);
420             }
421 2700         10480 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 209 my ($self, @co) = @_;
435            
436 123         232 foreach my $i (@co) {
437 4         15 $self->{CLASS_OF}->add($i);
438 4         15 $i->instance_of($self); # make the instance aware of its class (term)
439             }
440 123         506 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 102 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 4724 my $self = shift;
467 3389 50       9817 if (scalar(@_) > 1) {
    100          
468 0         0 $self->{INTERSECTION_OF}->add_all(@_);
469             } elsif (scalar(@_) == 1) {
470 4         14 $self->{INTERSECTION_OF}->add(shift);
471             }
472 3389         11231 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 4158 my $self = shift;
486 3387 50       8906 if (scalar(@_) > 1) {
    100          
487 0         0 $self->{UNION_OF}->add_all(@_);
488             } elsif (scalar(@_) == 1) {
489 2         8 $self->{UNION_OF}->add(shift);
490             }
491 3387         9314 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 4469 my $self = shift;
505 3402 100       8640 if (scalar(@_) > 1) {
    100          
506 1         5 $self->{DISJOINT_FROM}->add_all(@_);
507             } elsif (scalar(@_) == 1) {
508 15         50 $self->{DISJOINT_FROM}->add(shift);
509             }
510 3402         9968 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 2717 100   2717 1 6308 $_[0]->{CREATED_BY} = $_[1] if ($_[1]);
524 2717         8307 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 2719 100   2719 1 5310 $_[0]->{CREATION_DATE} = $_[1] if ($_[1]);
541 2719         7885 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 5288 $_[0]->{MODIFIED_BY} = $_[1] if ($_[1]);
556 2693         7208 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 4975 $_[0]->{MODIFICATION_DATE} = $_[1] if ($_[1]);
574 2693         7788 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 7212 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{IS_OBSOLETE} = $_[1] }
  31   66     63  
588 3421 100 66     15865 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 4355 my $self = shift;
602 3385 50       9328 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         12358 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 4287 my $self = shift;
621 3385 50       9096 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         10160 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 5980 if (defined $_[1] && ($_[1] == 1 || $_[1] == 0)) { $_[0]->{BUILTIN} = $_[1] }
  8   66     11  
640 2746 50 33     12000 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 164 if ($_[1] && eval { $_[1]->isa('OBO::Core::Term') }) {
  34         251  
654 34 50 33     326 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 1184 50   1184   2778 caller eq __PACKAGE__ or croak "You cannot call this (__dbxref) prived method!";
662             #
663             # $_[0] ==> set
664             # $_[1] ==> dbxref string
665             #
666 1184         1564 my $dbxref_set = $_[0];
667 1184         1503 my $dbxref_as_string = $_[1];
668            
669 1184         1830 $dbxref_as_string =~ s/^\[//;
670 1184         1823 $dbxref_as_string =~ s/\]$//;
671 1184         1720 $dbxref_as_string =~ s/\\,/;;;;/g; # trick to keep the comma's
672 1184         1694 $dbxref_as_string =~ s/\\"/;;;;;/g; # trick to keep the double quote's
673            
674 1184         2274 my @lineas = $dbxref_as_string =~ /\"([^\"]*)\"/g; # get the double-quoted pieces
675 1184         2111 foreach my $l (@lineas) {
676 8         14 my $cp = $l;
677 8         16 $l =~ s/,/;;;;/g; # trick to keep the comma's
678 8         135 $dbxref_as_string =~ s/\Q$cp\E/$l/;
679             }
680              
681 1184         3662 my $r_db_acc = qr/([ \*\.\w-]*):([ ;'\#~\w:\\\+\?\{\}\$\/\(\)\[\]\.=&!%_-]*)/o;
682 1184         3086 my $r_desc = qr/\s+\"([^\"]*)\"/o;
683 1184         2900 my $r_mod = qr/\s+(\{[\w ]+=[\w ]+\})/o;
684            
685 1184         3043 my @dbxrefs = split (',', $dbxref_as_string);
686              
687 1184         2097 foreach my $entry (@dbxrefs) {
688 1192         2017 my ($match, $db, $acc, $desc, $mod) = undef;
689 1192         3613 my $dbxref = OBO::Core::Dbxref->new();
690 1192 100       30581 if ($entry =~ m/$r_db_acc$r_desc$r_mod?/) {
    50          
691 8         21 $db = __unescape($1);
692 8         24 $acc = __unescape($2);
693 8         22 $desc = __unescape($3);
694 8 100       48 $mod = __unescape($4) if ($4);
695             } elsif ($entry =~ m/$r_db_acc$r_desc?$r_mod?/) {
696 1184         2423 $db = __unescape($1);
697 1184         2403 $acc = __unescape($2);
698 1184 50       3217 $desc = __unescape($3) if ($3);
699 1184 50       2803 $mod = __unescape($4) if ($4);
700             } else {
701 0         0 return (-1, $entry);
702             }
703            
704             # set the dbxref:
705 1192         5376 $dbxref->name($db.':'.$acc);
706 1192 100       3033 $dbxref->description($desc) if (defined $desc);
707 1192 100       2393 $dbxref->modifier($mod) if (defined $mod);
708 1192         3457 $dbxref_set->add($dbxref);
709             }
710 1184         4097 return 1;
711             }
712              
713             sub __unescape {
714 2395 50   2395   5298 caller eq __PACKAGE__ or die;
715 2395         4363 my $match = $_[0];
716 2395         3106 $match =~ s/;;;;;/\\"/g;
717 2395         3111 $match =~ s/;;;;/\\,/g;
718 2395         4836 return $match;
719             }
720              
721             1;
722              
723             __END__