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__ |