File Coverage

blib/lib/Objects/Collection.pm
Criterion Covered Total %
statement 49 109 44.9
branch 6 40 15.0
condition 2 6 33.3
subroutine 10 23 43.4
pod 7 9 77.7
total 74 187 39.5


line stmt bran cond sub pod time code
1             package Objects::Collection;
2              
3             #$Id: Collection.pm,v 1.6 2006/04/27 14:56:19 zag Exp $
4              
5             =head1 NAME
6              
7             Objects::Collection - Collections of data or objects.
8              
9             =head1 SYNOPSIS
10              
11             use Objects::Collection;
12             @Objects::Collection::AutoSQL::ISA = qw(Objects::Collection);
13              
14             =head1 DESCRIPTION
15              
16             A collection - sometimes called a container - is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data.
17              
18             =head1 METHODS
19              
20             =cut
21              
22 2     2   22625 use strict;
  2         5  
  2         68  
23 2     2   9 use warnings;
  2         4  
  2         45  
24 2     2   10 use Carp;
  2         4  
  2         146  
25 2     2   1039 use Data::Dumper;
  2         11227  
  2         119  
26 2     2   1294 use Objects::Collection::ActiveRecord;
  2         7  
  2         98  
27 2     2   13 use Objects::Collection::Base;
  2         4  
  2         88  
28 2     2   1076 use Objects::Collection::LazyObject;
  2         5  
  2         2407  
29             @Objects::Collection::ISA = qw(Objects::Collection::Base);
30             $Objects::Collection::VERSION = '0.37';
31             attributes qw( _obj_cache );
32              
33             sub _init {
34 2     2   12 my $self = shift;
35 2         65 $self->_obj_cache( {} );
36 2         14 $self->SUPER::_init(@_);
37             }
38              
39             =head2 _store( {ID1 => [, ID2 => , ...]} )
40              
41             Method for store changed objects. Called with ref to hash :
42              
43             {
44             ID1 =>
45             [,ID2 => ,...]
46             }
47              
48             =cut
49              
50             sub _store {
51 0     0   0 my $pkg = ref $_[0];
52 0         0 croak "$pkg doesn't define an _store method";
53             }
54              
55             =head2 _fetch({id=>ID1} [, {id=>ID2}, ...])
56              
57             Read data for given IDs. Must return reference to hash, where keys is IDs,
58             values is readed data.
59             For example:
60              
61             return {1=>[1..3],2=>[5..6]}
62            
63             =cut
64              
65             sub _fetch {
66 0     0   0 my $pkg = ref $_[0];
67 0         0 croak "$pkg doesn't define an _fetch method";
68             }
69              
70             =head2 _create()
71              
72             Create recods in data storage.
73              
74             Parametrs:
75              
76             user defined format
77              
78             Result:
79             Must return reference to hash, where keys is IDs, values is create records of data
80              
81             =cut
82              
83             sub _create {
84 0     0   0 my $pkg = ref $_[0];
85 0         0 croak "$pkg doesn't define an _create method";
86             }
87              
88             =head2 _delete(ID1[, ID2, ...]) or ({ id=>ID1 } [, {id => ID2 }, ...])
89              
90             Delete records in data storage for given IDs.
91              
92             Parametrs:
93             array id IDs
94              
95             ID1, ID2, ...
96              
97             or array of refs to HASHes
98              
99             { id=>ID1 }, {id => ID2 }, ...
100            
101              
102             Format of parametrs depend method L
103              
104             =cut
105              
106             sub _delete {
107 0     0   0 my $pkg = ref $_[0];
108 0         0 croak "$pkg doesn't define an _delete method";
109             }
110              
111             =head2 _prepare_record( ID1, )
112              
113             Called before insert readed objects into collection.
114             Must return ref to data or object, which will insert to callection.
115              
116             =cut
117              
118             sub _prepare_record {
119 0     0   0 my ( $self, $key, $ref ) = @_;
120 0         0 return $ref;
121             }
122              
123             =head2 create()
124              
125             Public method for create objects.
126              
127              
128             =cut
129              
130             sub create {
131 0     0 1 0 my $self = shift;
132 0         0 my $coll_ref = $self->_obj_cache();
133 0         0 my $results = $self->_create(@_);
134 0         0 return $self->fetch_objects( keys %$results );
135             }
136              
137             =head2 fetch_object(ID1)
138              
139             Public method. Fetch object from collection for given ID.
140             Return ref to objects or undef unless exists.
141              
142             =cut
143              
144             sub fetch_object {
145 3     3 1 7 my ( $self, $id ) = @_;
146 3         4 my $res;
147 3 50       15 if ( my $item_refs = $self->fetch_objects($id) ) {
148 3         5 $res = $item_refs->{$id};
149             }
150 3         21 return $res;
151             }
152              
153             =head2 fetch_objects(ID1 [, ID2, ...])
154              
155             Public method. Fetch objects from collection for given IDs.
156             Return ref to HASH, where where keys is IDs, values is objects refs.
157              
158              
159             Parametrs:
160              
161              
162             =cut
163              
164             sub fetch_objects {
165 3     3 1 5 my $self = shift;
166 3 50       18 my (@ids) =
167 3         5 map { ref($_) ? $_ : { id => $_ } } grep { defined $_ } @_;
  3         9  
168 3 50       10 return unless @ids;
169 3         101 my $coll_ref = $self->_obj_cache();
170 3   33     25 my (@fecth) =
171 3         6 grep { !exists $_->{id} or !exists $coll_ref->{ $_->{id} } } @ids;
172 3 50 33     23 if ( scalar(@fecth)
173             && ( my $results = $self->_fetch(@fecth) ) )
174             {
175              
176 2         10 map {
177 2         6 my $ref = $self->_prepare_record( $_, $results->{$_} );
178 2 50       23 $coll_ref->{$_} = $ref if ref($ref);
179             }
180              
181             #filter aleady loaded objects
182 3         8 grep { !exists $coll_ref->{$_} }
183 3         36 keys %{$results};
184 3         5 push @ids, map { { id => $_ } } keys %{$results};
  2         33  
  3         14  
185             }
186             return {
187 4 50       25 map { $_->{id} => $coll_ref->{ $_->{id} } }
  5         36  
188 3         49 grep { exists $_->{id} and exists $coll_ref->{ $_->{id} } } @ids
189             };
190             }
191              
192             =head2 release_objects(ID1[, ID2, ...])
193              
194             Release from collection objects with IDs.
195              
196             =cut
197              
198             sub release_objects {
199 0     0 1   my $self = shift;
200 0 0         my (@ids) = map { ref($_) ? $_ : { id => $_ } } @_;
  0            
201 0           my $coll_ref = $self->_obj_cache();
202 0 0         unless (@ids) {
203 0           my $res = [ map { { id => $_ } } keys %$coll_ref ];
  0            
204 0           undef %{$coll_ref};
  0            
205 0           return $res;
206             }
207             else {
208              
209             [
210 0           map {
211 0 0         delete $coll_ref->{ $_->{id} };
212 0           $_
213             }
214 0           map { ref($_) ? $_ : { id => $_ } } @ids
215             ];
216             } #else
217             }
218              
219             =head2 store_changed([ID1,[ID2,...]])
220              
221             Call _store for changed objects.
222             Store all all loaded objects without parameters:
223              
224             $simple_collection->store_changed(); #store all changed
225              
226             or (for 1,2,6 IDs )
227              
228             $simple_collection->store_changed(1,2,6);
229              
230             =cut
231              
232             sub store_changed {
233 0     0 1   my $self = shift;
234 0           my @store_ids = @_;
235 0           my $coll_ref = $self->_obj_cache();
236 0 0         @store_ids = keys %$coll_ref unless @store_ids;
237 0           my %to_store;
238 0           foreach my $id (@store_ids) {
239 0           my $ref = $coll_ref->{$id};
240 0 0         next unless ref($ref);
241 0 0         if ( ( ref($ref) eq 'HASH' ) ? $ref->{_changed} : $ref->_changed() ) {
    0          
242 0           $to_store{$id} = $ref;
243             }
244             }
245 0 0         if (%to_store) {
246 0           $self->_store( \%to_store );
247             }
248             }
249              
250             =head2 delete_objects(ID1[,ID2, ...])
251              
252             Release from collections and delete from storage (by calling L<_delete>)
253             objects ID1,ID2...
254              
255             $simple_collection->delete_objects(1,5,84);
256              
257              
258             =cut
259              
260             sub delete_objects {
261 0     0 1   my $self = shift;
262 0 0         my (@ids) = map { ref($_) ? $_ : { id => $_ } } @_;
  0            
263 0           $self->release_objects(@ids);
264 0           $self->_delete(@ids);
265             }
266              
267             =head2 get_lazy_object(ID1)
268              
269             Method for base support lazy load objects from data storage.
270             Not really return lazy object.
271              
272             =cut
273              
274             sub get_lazy_object {
275 0     0 1   my ( $self, $id ) = @_;
276             return new Objects::Collection::LazyObject::
277 0     0     sub { $self->fetch_object($id) };
  0            
278             }
279              
280             =head2
281              
282             =cut
283              
284             sub get_changed_id {
285 0     0 0   my $self = shift;
286 0           my $coll_ref = $self->_obj_cache();
287 0           my @changed = ();
288 0           while ( my ( $id, $value ) = each %$coll_ref ) {
289 0 0         if ( ref($value) eq 'HASH' ) {
290 0 0         if ( my $obj = tied $value ) {
291 0 0         push @changed, $id if $obj->_changed();
292             }
293             else {
294 0 0         push @changed, $id if $value->{_changed};
295             }
296             }
297             else {
298 0 0         push @changed, $id if $value->_changed();
299             }
300             }
301             return \@changed
302 0           }
303              
304             sub list_ids {
305 0     0 0   my $pkg = ref $_[0];
306 0           croak "$pkg doesn't define an list_ids method";
307             }
308             1;
309             __END__