ensembl-hive  2.5
Storable.pm
Go to the documentation of this file.
1 =pod
2 
3 =head1 NAME
4 
6 
7 =head1 SYNOPSIS
8 
9  my $dbID = $storable_object->dbID();
10  my $adaptor = $storable_object->adaptor();
11 
12 =head1 DESCRIPTION
13 
14  Storable is a base class for anything that can be stored.
15  It provides two getters/setters: dbID() and adaptor().
16 
17 =head1 LICENSE
18 
19  Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
20  Copyright [2016-2022] EMBL-European Bioinformatics Institute
21 
22  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
23  You may obtain a copy of the License at
24 
25  http://www.apache.org/licenses/LICENSE-2.0
26 
27  Unless required by applicable law or agreed to in writing, software distributed under the License
28  is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  See the License for the specific language governing permissions and limitations under the License.
30 
31 =head1 CONTACT
32 
33  Please contact ehive-users@ebi.ac.uk mailing list with questions/suggestions.
34 
35 =head1 APPENDIX
36 
37  The rest of the documentation details each of the object methods.
38  Internal methods are usually preceded with a _
39 
40 =cut
41 
42 
44 
45 use strict;
46 use warnings;
47 
48 use Scalar::Util qw(weaken);
49 use Bio::EnsEMBL::Hive::Utils ('throw');
51 
52 use base ( 'Bio::EnsEMBL::Hive::Cacheable' ); # All the Storable objects are attached to a pipeline, i.e. are Cacheable
53 
54 =head2 new
55 
56  Args : pairs of ($method_name, $value)
57  Caller : ObjectAdaptor, AnalysisJob, HivePipeline, seed_pipeline.pl, standaloneJob.pl
58  Description : create a new Storable object
59  Returntype : Bio::EnsEMBL::Hive::Storable
60  Status : stable
61 
62 =cut
63 
64 sub new {
65  my $class = shift @_;
66 
67  my $self = bless {}, $class;
68 
69  while(my ($method,$value) = splice(@_,0,2)) {
70  if(defined($value)) {
71  $self->$method($value);
72  }
73  }
74 
75  return $self;
76 }
77 
78 
79 =head2 dbID
80 
81  Arg [1] : int $dbID
82  Description : getter/setter for the database internal id
83  Returntype : int
84  Caller : general, set from adaptor on store
85  Status : stable
86 
87 =cut
88 
89 sub dbID {
90  my $self = shift;
91  $self->{'dbID'} = shift if(@_);
92  return $self->{'dbID'};
93 }
94 
95 
96 =head2 adaptor
97 
99  Description : getter/setter for this objects Adaptor
101  Caller : general, set from adaptor on store
102  Status : stable
103 
104 =cut
105 
106 sub adaptor {
107  my $self = shift;
108 
109  if(@_) {
110  $self->{'adaptor'} = shift;
111  weaken( $self->{'adaptor'} ) if defined( $self->{'adaptor'} );
112  }
113 
114  return $self->{'adaptor'};
115 }
116 
117 
118 sub DESTROY { } # "If you define an AUTOLOAD in your class,
119  # then Perl will call your AUTOLOAD to handle the DESTROY method.
120  # You can prevent this by defining an empty DESTROY (...)" -- perlobj
121 
122 sub AUTOLOAD {
123  our $AUTOLOAD;
124 
125 #print "Storable::AUTOLOAD : attempting to run '$AUTOLOAD' (".join(', ', @_).")\n";
126 
127  my $sub;
128 
129  if($AUTOLOAD =~ /::(\w+)$/) {
130  my $name_to_parse = $1;
131  my ($AdaptorType, $is_an_id, $foo_id_method_name, $foo_obj_method_name)
133 
134  unless($AdaptorType) {
135  throw("Storable::AUTOLOAD : could not parse '$name_to_parse'");
136  } elsif ($is_an_id) { # $name_to_parse was something like foo_dataflow_rule_id
137 
138  $sub = sub {
139  my $self = shift @_;
140  if(@_) {
141  $self->{$foo_id_method_name} = shift @_;
142 
143  $self->{$foo_obj_method_name} = undef; # invalidate the object itself
144 
145  # attempt to lazy-load:
146  } elsif( !$self->{$foo_id_method_name} and my $foo_object=$self->{$foo_obj_method_name}) {
147  $self->{$foo_id_method_name} = $foo_object->dbID;
148 # warn "Lazy-loaded dbID (".$self->{$foo_id_method_name}.") from $AdaptorType object\n";
149  }
150 
151  return $self->{$foo_id_method_name};
152  };
153 
154  } else { # $name_to_parse was something like foo_dataflow_rule
155 
156  $sub = sub {
157  my $self = shift @_;
158  if(@_) { # setter of the object itself
159  $self->{$foo_obj_method_name} = shift @_;
160 
161  $self->{$foo_id_method_name} = undef; # invalidate the object_id
162 
163  # attempt to lazy-load:
164  } elsif( !$self->{$foo_obj_method_name} and my $foo_object_id = $self->{$foo_id_method_name}) {
165  my $collection = $self->hive_pipeline && $self->hive_pipeline->collection_of($AdaptorType);
166 
167  if( $collection and $self->{$foo_obj_method_name} = $collection->find_one_by('dbID', $foo_object_id) ) { # careful: $AdaptorType may not be unique (aliases)
168  weaken($self->{$foo_obj_method_name});
169 # warn "Lazy-loading object from $AdaptorType collection\n";
170  } elsif(my $adaptor = $self->adaptor) {
171 # warn "Lazy-loading object from $AdaptorType adaptor\n";
172  $self->{$foo_obj_method_name} = $adaptor->db->get_adaptor( $AdaptorType )->fetch_by_dbID( $foo_object_id );
173  } else {
174 # warn "Cannot lazy-load $foo_obj_method_name because the ".ref($self)." is not attached to an adaptor";
175  }
176  }
177 
178  return $self->{$foo_obj_method_name};
179  };
180 
181  } # choice of autoloadable functions
182  {
183  no strict 'refs'; ## no critic ProhibitNoStrict
184  *{$AUTOLOAD} = $sub;
185  goto &$sub;
186  }
187 
188  }
189 }
190 
191 1;
192