]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm
record_marc is now merged into record_entry
[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::action;
8 use OpenILS::Application::Storage::CDBI::asset;
9 use OpenILS::Application::Storage::CDBI::biblio;
10 use OpenILS::Application::Storage::CDBI::metabib;
11 use OpenILS::Application::Storage::CDBI::money;
12
13 use OpenSRF::Utils::Logger;
14
15 our $VERSION;
16 my $log = 'OpenSRF::Utils::Logger';
17
18 sub child_init {
19         my $self = shift;
20
21         $log->debug("Creating ImaDBI Querys", DEBUG);
22         __PACKAGE__->set_sql( 'OILSFastSearch', <<"     SQL", 'Main');
23                 SELECT  %s
24                   FROM  %s
25                   WHERE %s = ?
26         SQL
27
28         __PACKAGE__->set_sql( 'OILSFastOrderedSearchLike', <<"  SQL", 'Main');
29                 SELECT  %s
30                   FROM  %s
31                   WHERE %s ~ ?
32                   ORDER BY %s
33         SQL
34
35         __PACKAGE__->set_sql( 'OILSFastOrderedSearch', <<"      SQL", 'Main');
36                 SELECT  %s
37                   FROM  %s
38                   WHERE %s = ?
39                   ORDER BY %s
40         SQL
41
42         $log->debug("Calling Driver child_init", DEBUG);
43         $self->SUPER::child_init(@_);
44
45 }
46
47 sub fast_flesh_sth {
48         my $class = shift;
49         $class = ref($class) || $class;
50
51         my $field = shift;
52         my $value = shift;
53         my $order = shift;
54         my $like = shift;
55
56
57         if (!(defined($order) and ref($order) and ref($order) eq 'HASH')) {
58                 if (defined($value) and ref($value) and ref($value) eq 'HASH') {
59                         $order = $value;
60                         $value = undef;
61                 } else {
62                         $order = { order_by => $class->columns('Primary') }
63                 }
64         }
65
66         unless (defined $value) {
67                 $value = $field;
68                 $field = $class->primary_column;
69         }
70
71         unless (defined $field) {
72                 $field = $class->primary_column;
73         }
74
75         unless ($order->{order_by}) {
76                 $order = { order_by => $class->columns('Primary') }
77         }
78
79         my $fm_class = 'Fieldmapper::'.$class;
80         my $field_list = join ',', $class->columns('All');
81         
82         my $sth;
83         if (!$like) {
84                 $sth = $class->sql_OILSFastOrderedSearch( $field_list, $class->table, $field, $order->{order_by});
85         } else {
86                 $sth = $class->sql_OILSFastOrderedSearchLike( $field_list, $class->table, $field, $order->{order_by});
87         }
88         $sth->execute($value);
89         return $sth;
90 }
91
92 sub fast_flesh {
93         my $self = shift;
94         return map $class->construct($_), $self->fast_flesh_sth(@_)->fetchall_hash;
95 }
96
97 sub fast_fieldmapper {
98         my $self = shift;
99         my $id = shift;
100         my $col = shift;
101         my $like = shift;
102         my $class = ref($self) || $self;
103         my $fm_class = 'Fieldmapper::'.$class;
104         my @fms;
105         $log->debug("fast_fieldmapper() ==> Retrieving $fm_class", INTERNAL);
106         for my $hash ($self->fast_flesh_sth( $col, "$id", { order_by => $col }, $like )->fetchall_hash) {
107                 my $fm = $fm_class->new;
108                 for my $field ( $fm_class->real_fields ) {
109                         $fm->$field( $$hash{$field} );
110                 }
111                 push @fms, $fm;
112         }
113         return @fms;
114 }
115
116 sub retrieve {
117         my $self = shift;
118         my $arg = shift;
119         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
120                 $arg = $arg->id;
121         }
122         $log->debug("Retrieving $self with $arg", INTERNAL);
123         my $rec =  $self->SUPER::retrieve("$arg");
124         unless ($rec) {
125                 $log->debug("Could not retrieve $self with $arg!", DEBUG);
126                 return undef;
127         }
128         return $rec;
129 }
130
131 sub to_fieldmapper {
132         my $obj = shift;
133         my $class = ref($obj) || $obj;
134
135         my $fm_class = 'Fieldmapper::'.$class;
136         my $fm = $fm_class->new;
137
138         if (ref($obj)) {
139                 for my $field ( $fm->real_fields ) {
140                         $fm->$field( $obj->$field );
141                 }
142         }
143
144         return $fm;
145 }
146
147 sub create {
148         my $self = shift;
149         my $arg = shift;
150
151         $log->debug("\$arg is $arg (".ref($arg).")",DEBUG);
152
153         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
154                 return $self->create_from_fieldmapper($arg,@_);
155         }
156
157         return $self->SUPER::create($arg,@_);
158 }
159
160 sub create_from_fieldmapper {
161         my $obj = shift;
162         my $fm = shift;
163         my @params = @_;
164
165         $log->debug("Creating node of type ".ref($fm), DEBUG);
166
167         my $class = ref($obj) || $obj;
168
169         if (ref $fm) {
170                 my %hash = map { defined $fm->$_ ?
171                                         ($_ => $fm->$_) :
172                                         ()
173                                 } $fm->real_fields;
174
175                 if ($class->find_column( 'last_xact_id' )) {
176                         my $xact_id = $class->current_xact_id;
177                         throw Error unless ($xact_id);
178                         $hash{last_xact_id} = $xact_id;
179                 }
180
181                 return $class->create( \%hash, @params );
182         } else {
183                 return undef;
184         }
185 }
186
187 sub delete {
188         my $self = shift;
189         my $arg = shift;
190
191         my $class = ref($self) || $self;
192
193         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
194                 $self = $self->retrieve($arg);
195                 unless (defined $self) {
196                         $log->debug("ARG! Couldn't retrieve record ".$arg->id, DEBUG);
197                         throw OpenSRF::EX::WARN ("ARG! Couldn't retrieve record ");
198                 }
199         }
200
201         if ($class->find_column( 'last_xact_id' )) {
202                 my $xact_id = $self->current_xact_id;
203                 throw Error unless ($xact_id);
204                 $self->last_xact_id( $class->current_xact_id );
205                 $self->SUPER::update;
206         }
207
208         $self->SUPER::delete;
209         return 1;
210 }
211
212 sub update {
213         my $self = shift;
214         my $arg = shift;
215
216         $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
217
218         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
219                 $self = $self->modify_from_fieldmapper($arg);
220                 $log->debug("Modification of $self seems to have failed....", DEBUG);
221                 return undef unless (defined $self);
222         }
223
224         $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
225         return $self->SUPER::update if ($self->is_changed);
226         return 0;
227 }
228
229 sub modify_from_fieldmapper {
230         my $obj = shift;
231         my $fm = shift;
232
233         $log->debug("Modifying object using fieldmapper", DEBUG);
234
235         my $class = ref($obj) || $obj;
236
237         if (!ref($obj)) {
238                 $obj = $class->retrieve($fm);
239                 unless ($obj) {
240                         $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
241                         throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
242                 }
243
244         }
245
246         my %hash = map { defined $fm->$_ ?
247                                 ($_ => $fm->$_) :
248                                 ()
249                         } $fm->real_fields;
250
251         my $au = $obj->autoupdate;
252         $obj->autoupdate(0);
253         
254         for my $field ( keys %hash ) {
255                 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
256                 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
257         }
258
259         if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
260                 my $xact_id = $obj->current_xact_id;
261                 throw Error unless ($xact_id);
262                 $obj->last_xact_id( $xact_id );
263         } else {
264                 $obj->autoupdate($au)
265         }
266
267         return $obj;
268 }
269
270
271
272 sub import {
273         return if ($VERSION);
274         #-------------------------------------------------------------------------------
275         actor::user->has_a( home_ou => 'actor::org_unit' );
276         actor::user->has_many( survey_responses => 'action::survey_response' );
277         #-------------------------------------------------------------------------------
278         actor::org_unit->has_many( users => 'actor::user' );
279         actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
280         actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
281         #actor::org_unit->has_a( address => 'actor::address' );
282         #-------------------------------------------------------------------------------
283
284         #-------------------------------------------------------------------------------
285         action::survey_response->has_a( usr => 'actor::user' );
286         action::survey_response->has_a( survey => 'action::survey' );
287         action::survey_response->has_a( question => 'action::survey_question' );
288         action::survey_response->has_a( answer => 'action::survey_answer' );
289         #-------------------------------------------------------------------------------
290         action::survey->has_many( questions => 'action::survey_question' );
291         action::survey->has_many( responses => 'action::survey_response' );
292         #-------------------------------------------------------------------------------
293         action::survey_question->has_a( survey => 'action::survey' );
294         action::survey_question->has_many( answers => 'action::survey_answer' );
295         action::survey_question->has_many( responses => 'action::survey_response' );
296         #-------------------------------------------------------------------------------
297         action::survey_answer->has_a( question => 'action::survey' );
298         action::survey_answer->has_many( responses => 'action::survey_response' );
299         #-------------------------------------------------------------------------------
300
301         #-------------------------------------------------------------------------------
302         asset::copy_note->has_a( owning_copy => 'asset::copy' );
303         #-------------------------------------------------------------------------------
304         asset::copy->has_a( call_number => 'asset::call_number' );
305         asset::copy->has_many( notes => 'asset::copy_note' );
306         asset::copy->has_a( creator => 'actor::user' );
307         asset::copy->has_a( editor => 'actor::user' );
308         #-------------------------------------------------------------------------------
309         asset::call_number_note->has_a( owning_call_number => 'asset::call_number' );
310         #-------------------------------------------------------------------------------
311         asset::call_number->has_a( record => 'biblio::record_entry' );
312         asset::call_number->has_many( copies => 'asset::copy' );
313         asset::call_number->has_many( notes => 'asset::call_number_note' );
314         asset::call_number->has_a( creator => 'actor::user' );
315         asset::call_number->has_a( editor => 'actor::user' );
316         #-------------------------------------------------------------------------------
317         
318
319         #-------------------------------------------------------------------------------
320         biblio::record_note->has_a( record => 'biblio::record_entry' );
321         #-------------------------------------------------------------------------------
322         biblio::record_entry->has_a( creator => 'actor::user' );
323         biblio::record_entry->has_a( editor => 'actor::user' );
324         biblio::record_entry->has_many( record_descriptor => 'metabib::record_descriptor' );
325         biblio::record_entry->has_many( notes => 'biblio::record_note' );
326         biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
327         
328         # should we have just one field entry per class for each record???? (xslt vs xpath)
329         biblio::record_entry->has_many( full_record_entries => 'metabib::full_rec' );
330         biblio::record_entry->has_many( title_field_entries => 'metabib::title_field_entry' );
331         biblio::record_entry->has_many( author_field_entries => 'metabib::author_field_entry' );
332         biblio::record_entry->has_many( subject_field_entries => 'metabib::subject_field_entry' );
333         biblio::record_entry->has_many( keyword_field_entries => 'metabib::keyword_field_entry' );
334         #-------------------------------------------------------------------------------
335
336
337         #-------------------------------------------------------------------------------
338         metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
339         metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source'] );
340         #-------------------------------------------------------------------------------
341         metabib::record_descriptor->has_a( record => 'biblio::record_entry' );
342         #-------------------------------------------------------------------------------
343         metabib::full_rec->has_a( record => 'biblio::record_entry' );
344         #-------------------------------------------------------------------------------
345         metabib::title_field_entry->has_a( source => 'biblio::record_entry' );
346         metabib::title_field_entry->has_a( field => 'config::metabib_field' );
347         #-------------------------------------------------------------------------------
348         metabib::author_field_entry->has_a( source => 'biblio::record_entry' );
349         metabib::author_field_entry->has_a( field => 'config::metabib_field' );
350         #-------------------------------------------------------------------------------
351         metabib::subject_field_entry->has_a( source => 'biblio::record_entry' );
352         metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
353         #-------------------------------------------------------------------------------
354         metabib::keyword_field_entry->has_a( source => 'biblio::record_entry' );
355         metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
356         #-------------------------------------------------------------------------------
357         metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
358         metabib::metarecord_source_map->has_a( source => 'biblio::record_entry' );
359         #-------------------------------------------------------------------------------
360
361         action::circulation->has_a( usr => 'actor::user' );
362         action::circulation->has_a( target_copy => 'asset::copy' );
363
364         #-------------------------------------------------------------------------------
365
366         money::billable_transaction->has_a( usr => 'actor::user' );
367         money::billable_transaction->has_many( billings => 'money::billing' );
368         money::billable_transaction->has_many( payments => 'money::payment' );
369
370         money::billing->has_a( transaction => 'money::billable_transaction' );
371         money::payment->has_a( transaction => 'money::billable_transaction' );
372
373         money::cash_payment->has_a( transaction => 'money::billable_transaction' );
374         money::cash_payment->has_a( accepting_usr => 'actor::user' );
375
376         money::check_payment->has_a( transaction => 'money::billable_transaction' );
377         money::check_payment->has_a( accepting_usr => 'actor::user' );
378
379         money::credit_card_payment->has_a( transaction => 'money::billable_transaction' );
380         money::credit_card_payment->has_a( accepting_usr => 'actor::user' );
381
382         money::forgive_payment->has_a( transaction => 'money::billable_transaction' );
383         money::forgive_payment->has_a( accepting_usr => 'actor::user' );
384
385         money::work_payment->has_a( transaction => 'money::billable_transaction' );
386         money::work_payment->has_a( accepting_usr => 'actor::user' );
387
388         money::credit_payment->has_a( transaction => 'money::billable_transaction' );
389         money::credit_payment->has_a( accepting_usr => 'actor::user' );
390
391
392         # should we have just one field entry per class for each record???? (xslt vs xpath)
393         #metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
394         #metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
395         #metabib::title_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
396         #-------------------------------------------------------------------------------
397         #metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
398         #metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
399         #metabib::subject_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
400         #-------------------------------------------------------------------------------
401         #metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
402         #metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
403         #metabib::author_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
404         #-------------------------------------------------------------------------------
405         #metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
406         #metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
407         #metabib::keyword_field_entry_source_map->has_a( metarecord => 'metabib::metarecord' );
408         #-------------------------------------------------------------------------------
409         $VERSION = 1;
410 }
411
412
413 1;