]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm
eet leevs
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / CDBI.pm
1 package OpenILS::Application::Storage::CDBI;
2 use base qw/Class::DBI/;
3 use Class::DBI;
4
5 use OpenILS::Application::Storage::CDBI::config;
6 use OpenILS::Application::Storage::CDBI::actor;
7 use OpenILS::Application::Storage::CDBI::asset;
8 use OpenILS::Application::Storage::CDBI::biblio;
9 use OpenILS::Application::Storage::CDBI::metabib;
10
11 use OpenILS::Utils::Fieldmapper;
12 use OpenSRF::Utils::Logger;
13
14 our $VERSION;
15 my $log = 'OpenSRF::Utils::Logger';
16
17 sub child_init {
18         my $self = shift;
19
20         $log->debug("Creating ImaDBI Querys", DEBUG);
21         __PACKAGE__->set_sql( 'OILSFastSearch', <<"     SQL", 'Main');
22                 SELECT  %s
23                   FROM  %s
24                   WHERE %s = ?
25         SQL
26
27         __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<"      SQL", 'Main');
28                 SELECT  %s
29                   FROM  %s
30                   WHERE %s = ?
31                   ORDER BY %s
32         SQL
33
34         $log->debug("Calling Driver child_init", DEBUG);
35         $self->SUPER::child_init(@_);
36
37 }
38
39 sub fast_flesh_sth {
40         my $class = shift;
41         $class = ref($class) || $class;
42
43         my $field = shift;
44         my $value = shift;
45         my $order = shift;
46
47         if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
48                 if (defined($value) and ref($order) and ref($order) eq 'HASH') {
49                         $order = $value;
50                         $value = $field;
51                         $field = $class->primary_column;
52                 } else {
53                         $order = { order_by => 'id' }
54                 }
55         }
56
57         unless (defined $value) {
58                 $value = $field;
59                 $field = $class->primary_column;
60         }
61
62         my $fm_class = 'Fieldmapper::'.$class;
63         my $field_list = join ',', $class->columns('All');
64         
65         my $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
66         $sth->execute($value);
67         return $sth;
68 }
69
70 sub fast_flesh {
71         my $self = shift;
72         return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
73 }
74
75 sub fast_fieldmapper {
76         my $self = shift;
77         my $class = ref($self) || $self;
78         my $fm_class = 'Fieldmapper::'.$class;
79         my @fms;
80         $log->debug("fast_fieldmapper() ==> Retrieving $fm_class", INTERNAL);
81         for my $hash ($self->fast_flesh_sth(map {"$_"} @_)->fetchall_hash) {
82                 my $fm = $fm_class->new;
83                 for my $field ( keys %$hash ) {
84                         $fm->$field( $$hash{$field} );
85                 }
86                 push @fms, $fm;
87         }
88         return @fms;
89 }
90
91 sub retrieve {
92         my $self = shift;
93         my $arg = shift;
94         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
95                 $arg = $arg->id;
96         }
97         $log->debug("Retrieving $self with $arg", INTERNAL);
98         my $rec =  $self->SUPER::retrieve("$arg");
99         unless ($rec) {
100                 $log->debug("Could not retrieve $self with $arg!", DEBUG);
101                 return undef;
102         }
103         return $rec;
104 }
105
106 sub to_fieldmapper {
107         my $obj = shift;
108         my $class = ref($obj) || $obj;
109
110         my $fm_class = 'Fieldmapper::'.$class;
111         my $fm = $fm_class->new;
112
113         if (ref($obj)) {
114                 for my $field ( $fm->real_fields ) {
115                         $fm->$field( $obj->$field );
116                 }
117         }
118
119         return $fm;
120 }
121
122 sub create {
123         my $self = shift;
124         my $arg = shift;
125
126         $log->debug("\$arg is $arg (".ref($arg).")",DEBUG);
127
128         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
129                 return $self->create_from_fieldmapper($arg,@_);
130         }
131
132         return $self->SUPER::create($arg,@_);
133 }
134
135 sub create_from_fieldmapper {
136         my $obj = shift;
137         my $fm = shift;
138         my @params = @_;
139
140         $log->debug("Creating node of type ".ref($fm), DEBUG);
141
142         my $class = ref($obj) || $obj;
143
144         if (ref $fm) {
145                 my %hash = map { defined $fm->$_ ?
146                                         ($_ => $fm->$_) :
147                                         ()
148                                 } $fm->real_fields;
149
150                 if ($class->find_column( 'last_xact_id' )) {
151                         my $xact_id = $class->current_xact_id;
152                         throw Error unless ($xact_id);
153                         $hash{last_xact_id} = $xact_id;
154                 }
155
156                 return $class->create( \%hash, @params );
157         } else {
158                 return undef;
159         }
160 }
161
162 sub delete {
163         my $self = shift;
164         my $arg = shift;
165
166         my $class = ref($self) || $self;
167
168         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
169                 $self = $self->retrieve($arg);
170                 unless (defined $self) {
171                         $log->debug("ARG! Couldn't retrieve record ".$arg->id, DEBUG);
172                         throw OpenSRF::EX::WARN ("ARG! Couldn't retrieve record ");
173                 }
174         }
175
176         if ($class->find_column( 'last_xact_id' )) {
177                 my $xact_id = $self->current_xact_id;
178                 throw Error unless ($xact_id);
179                 $self->last_xact_id( $class->current_xact_id );
180                 $self->SUPER::update;
181         }
182
183         $self->SUPER::delete;
184         return 1;
185 }
186
187 sub update {
188         my $self = shift;
189         my $arg = shift;
190
191         $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
192
193         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
194                 $self = $self->modify_from_fieldmapper($arg);
195                 $log->debug("Modification of $self seems to have failed....", DEBUG);
196                 return undef unless (defined $self);
197         }
198
199         $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
200         return $self->SUPER::update if ($self->is_changed);
201         return 0;
202 }
203
204 sub modify_from_fieldmapper {
205         my $obj = shift;
206         my $fm = shift;
207
208         $log->debug("Modifying object using fieldmapper", DEBUG);
209
210         my $class = ref($obj) || $obj;
211
212         if (!ref($obj)) {
213                 $obj = $class->retrieve($fm);
214                 unless ($obj) {
215                         $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
216                         throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
217                 }
218
219         }
220
221         my %hash = map { defined $fm->$_ ?
222                                 ($_ => $fm->$_) :
223                                 ()
224                         } $fm->real_fields;
225
226         my $au = $obj->autoupdate;
227         $obj->autoupdate(0);
228         
229         for my $field ( keys %hash ) {
230                 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
231                 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
232         }
233
234         if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
235                 my $xact_id = $obj->current_xact_id;
236                 throw Error unless ($xact_id);
237                 $obj->last_xact_id( $xact_id );
238         } else {
239                 $obj->autoupdate($au)
240         }
241
242         return $obj;
243 }
244
245
246
247 sub import {
248         return if ($VERSION);
249         #-------------------------------------------------------------------------------
250         actor::user->has_a( home_ou => 'actor::org_unit' );
251         #actor::org_unit->has_a( address => 'actor::address' );
252         #-------------------------------------------------------------------------------
253         actor::org_unit->has_many( users => 'actor::user' );
254         actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
255         actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
256         #actor::org_unit->has_a( address => 'actor::address' );
257         #-------------------------------------------------------------------------------
258
259         #-------------------------------------------------------------------------------
260         asset::copy->has_a( call_number => 'asset::call_number' );
261         #asset::copy->might_have( metadata => 'asset::copy_metadata' );
262         #-------------------------------------------------------------------------------
263         #asset::copy_metadata->might_have( copy => 'asset::copy' );
264         asset::copy_metadata->has_a( circulating_location => 'actor::org_unit');
265         asset::copy_metadata->has_a( hold_radius => 'actor::org_unit_type');
266         #-------------------------------------------------------------------------------
267         asset::call_number->has_a( record => 'biblio::record_entry' );
268         asset::call_number->has_many( copies => 'asset::copy' );
269         #-------------------------------------------------------------------------------
270         
271
272         #-------------------------------------------------------------------------------
273         biblio::record_note->has_a( record => 'biblio::record_entry' );
274         #-------------------------------------------------------------------------------
275         biblio::record_mods->is_a( id => 'biblio::record_entry' );
276         #-------------------------------------------------------------------------------
277         biblio::record_marc->is_a( id => 'biblio::record_entry' );
278         #-------------------------------------------------------------------------------
279         biblio::record_entry->has_a( creator => 'actor::user' );
280         biblio::record_entry->has_a( editor => 'actor::user' );
281         biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
282         biblio::record_entry->might_have( marc_entry => 'biblio::record_marc' => qw/marc/ );
283         biblio::record_entry->has_many( notes => 'biblio::record_note' );
284         biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
285         biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
286         
287         # should we have just one field entry per class for each record???? (xslt vs xpath)
288         #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
289         #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
290         #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
291         #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
292         #-------------------------------------------------------------------------------
293         biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
294         #biblio::record_node->has_a(
295         #       parent_node     => 'biblio::record_node::subnode',
296         #       inflate         => sub { return biblio::record_node::subnode::_load(@_) }
297         #);
298         #-------------------------------------------------------------------------------
299         
300         #-------------------------------------------------------------------------------
301         metabib::full_rec->has_a( record => 'biblio::record_entry' );
302         #-------------------------------------------------------------------------------
303         metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
304         metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
305         #-------------------------------------------------------------------------------
306         metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
307         metabib::title_field_entry->has_a( field => 'config::metabib_field' );
308         #-------------------------------------------------------------------------------
309         metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
310         metabib::author_field_entry->has_a( field => 'config::metabib_field' );
311         #-------------------------------------------------------------------------------
312         metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
313         metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
314         #-------------------------------------------------------------------------------
315         metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
316         metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
317         #-------------------------------------------------------------------------------
318         metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
319         metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
320         #-------------------------------------------------------------------------------
321
322
323         # should we have just one field entry per class for each record???? (xslt vs xpath)
324         metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
325         metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
326         metabib::title_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
327         #-------------------------------------------------------------------------------
328         metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
329         metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
330         metabib::subject_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
331         #-------------------------------------------------------------------------------
332         metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
333         metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
334         metabib::author_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
335         #-------------------------------------------------------------------------------
336         metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
337         metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
338         metabib::keyword_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
339         #-------------------------------------------------------------------------------
340         $VERSION = 1;
341 }
342
343
344 1;