]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm
1178979be227e002bd5e32b96c60ab1d16834210
[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         for my $hash ($self->fast_flesh_sth(@_)->fetchall_hash) {
81                 my $fm = $fm_class->new;
82                 for my $field ( keys %$hash ) {
83                         $fm->$field( $$hash{$field} );
84                 }
85                 push @fms, $fm;
86         }
87         return @fms;
88 }
89
90 sub retrieve {
91         my $self = shift;
92         my $arg = shift;
93         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
94                 $arg = $arg->id;
95         }
96         $log->debug("Retrieving $self with $arg", INTERNAL);
97         my $rec =  $self->SUPER::retrieve("$arg");
98         unless ($rec) {
99                 $log->debug("Could not retrieve $self with $arg!", DEBUG);
100                 return undef;
101         }
102         return $rec;
103 }
104
105 sub to_fieldmapper {
106         my $obj = shift;
107         my $class = ref($obj) || $obj;
108
109         my $fm_class = 'Fieldmapper::'.$class;
110         my $fm = $fm_class->new;
111
112         if (ref($obj)) {
113                 for my $field ( $fm->real_fields ) {
114                         $fm->$field( $obj->$field );
115                 }
116         }
117
118         return $fm;
119 }
120
121 sub create {
122         my $self = shift;
123         my $arg = shift;
124
125         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
126                 return $self->create_from_fieldmapper($arg,@_);
127         }
128
129         return $self->SUPER::create($arg,@_);
130 }
131
132 sub create_from_fieldmapper {
133         my $obj = shift;
134         my $fm = shift;
135         my @params = @_;
136
137         my $class = ref($obj) || $obj;
138
139         if (ref $fm) {
140                 my %hash = map { defined $fm->$_ ?
141                                         ($_ => $fm->$_) :
142                                         ()
143                                 } $fm->real_fields;
144
145                 if ($class->find_column( 'last_xact_id' )) {
146                         my $xact_id = $class->current_xact_id;
147                         throw Error unless ($xact_id);
148                         $hash{last_xact_id} = $xact_id;
149                 }
150
151                 return $class->create( \%hash, @params );
152         } else {
153                 return undef;
154         }
155 }
156
157 sub delete {
158         my $self = shift;
159         my $arg = shift;
160
161         my $class = ref($self) || $self;
162
163         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
164                 $self = $self->retrieve($arg);
165                 unless (defined $self) {
166                         $log->debug("ARG! Couldn't retrieve record ".$arg->id, DEBUG);
167                         throw OpenSRF::EX::WARN ("ARG! Couldn't retrieve record ");
168                 }
169         }
170
171         if ($class->find_column( 'last_xact_id' )) {
172                 my $xact_id = $self->current_xact_id;
173                 throw Error unless ($xact_id);
174                 $self->last_xact_id( $class->current_xact_id );
175                 $self->SUPER::update;
176         }
177
178         $self->SUPER::delete;
179         return 1;
180 }
181
182 sub update {
183         my $self = shift;
184         my $arg = shift;
185
186         $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
187
188         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
189                 $self = $self->modify_from_fieldmapper($arg);
190                 $log->debug("Modification of $self seems to have failed....", DEBUG);
191                 return undef unless (defined $self);
192         }
193
194         $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
195         return $self->SUPER::update if ($self->is_changed);
196         return 0;
197 }
198
199 sub modify_from_fieldmapper {
200         my $obj = shift;
201         my $fm = shift;
202
203         $log->debug("Modifying object using fieldmapper", DEBUG);
204
205         my $class = ref($obj) || $obj;
206
207         if (!ref($obj)) {
208                 $obj = $class->retrieve($fm);
209                 unless ($obj) {
210                         $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
211                         throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
212                 }
213
214         }
215
216         my %hash = map { defined $fm->$_ ?
217                                 ($_ => $fm->$_) :
218                                 ()
219                         } $fm->real_fields;
220
221         my $au = $obj->autoupdate;
222         $obj->autoupdate(0);
223         
224         for my $field ( keys %hash ) {
225                 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
226                 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
227         }
228
229         if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
230                 my $xact_id = $obj->current_xact_id;
231                 throw Error unless ($xact_id);
232                 $obj->last_xact_id( $xact_id );
233         } else {
234                 $obj->autoupdate($au)
235         }
236
237         return $obj;
238 }
239
240
241
242 sub import {
243         return if ($VERSION);
244         #-------------------------------------------------------------------------------
245         actor::user->has_a( home_ou => 'actor::org_unit' );
246         #actor::org_unit->has_a( address => 'actor::address' );
247         #-------------------------------------------------------------------------------
248         actor::org_unit->has_many( users => 'actor::user' );
249         actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
250         actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
251         #actor::org_unit->has_a( address => 'actor::address' );
252         #-------------------------------------------------------------------------------
253
254         #-------------------------------------------------------------------------------
255         asset::copy->has_a( call_number => 'asset::call_number' );
256         #asset::copy->might_have( metadata => 'asset::copy_metadata' );
257         #-------------------------------------------------------------------------------
258         #asset::copy_metadata->might_have( copy => 'asset::copy' );
259         asset::copy_metadata->has_a( circulating_location => 'actor::org_unit');
260         asset::copy_metadata->has_a( hold_radius => 'actor::org_unit_type');
261         #-------------------------------------------------------------------------------
262         asset::call_number->has_a( record => 'biblio::record_entry' );
263         asset::call_number->has_many( copies => 'asset::copy' );
264         #-------------------------------------------------------------------------------
265         
266
267         #-------------------------------------------------------------------------------
268         biblio::record_note->has_a( record => 'biblio::record_entry' );
269         #-------------------------------------------------------------------------------
270         biblio::record_mods->is_a( id => 'biblio::record_entry' );
271         #-------------------------------------------------------------------------------
272         biblio::record_marc->is_a( id => 'biblio::record_entry' );
273         #-------------------------------------------------------------------------------
274         biblio::record_entry->has_a( creator => 'actor::user' );
275         biblio::record_entry->has_a( editor => 'actor::user' );
276         biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
277         biblio::record_entry->might_have( marc_entry => 'biblio::record_marc' => qw/marc/ );
278         biblio::record_entry->has_many( notes => 'biblio::record_note' );
279         biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
280         biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
281         
282         # should we have just one field entry per class for each record???? (xslt vs xpath)
283         #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
284         #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
285         #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
286         #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
287         #-------------------------------------------------------------------------------
288         biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
289         #biblio::record_node->has_a(
290         #       parent_node     => 'biblio::record_node::subnode',
291         #       inflate         => sub { return biblio::record_node::subnode::_load(@_) }
292         #);
293         #-------------------------------------------------------------------------------
294         
295         #-------------------------------------------------------------------------------
296         metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
297         metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
298         #-------------------------------------------------------------------------------
299         metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
300         metabib::title_field_entry->has_a( field => 'config::metabib_field' );
301         #-------------------------------------------------------------------------------
302         metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
303         metabib::author_field_entry->has_a( field => 'config::metabib_field' );
304         #-------------------------------------------------------------------------------
305         metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
306         metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
307         #-------------------------------------------------------------------------------
308         metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
309         metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
310         #-------------------------------------------------------------------------------
311         metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
312         metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
313         #-------------------------------------------------------------------------------
314
315
316         # should we have just one field entry per class for each record???? (xslt vs xpath)
317         metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
318         metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
319         #-------------------------------------------------------------------------------
320         metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
321         metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
322         #-------------------------------------------------------------------------------
323         metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
324         metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
325         #-------------------------------------------------------------------------------
326         metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
327         metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
328         #-------------------------------------------------------------------------------
329         $VERSION = 1;
330 }
331
332
333 1;