]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI.pm
automatic generation of most "Publish" methods
[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         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         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
162                 $self = $self->retrieve($arg);
163         }
164
165         if ($class->find_column( 'last_xact_id' )) {
166                 my $xact_id = $self->current_xact_id;
167                 throw Error unless ($xact_id);
168                 $self->last_xact_id( $self->current_xact_id );
169                 $self->update;
170         }
171
172         $self->SUPER::delete;
173         return $arg;
174 }
175
176 sub update {
177         my $self = shift;
178         my $arg = shift;
179
180         $log->debug("Attempting to update using $arg", DEBUG) if ($arg);
181
182         if (ref($arg) and UNIVERSAL::isa($arg => 'Fieldmapper')) {
183                 $self = $self->modify_from_fieldmapper($arg);
184                 $log->debug("Modification of $self seems to have failed....", DEBUG);
185                 return undef unless (defined $self);
186         }
187
188         $log->debug("Calling Class::DBI->update on modified object $self", DEBUG);
189         return $self->SUPER::update if ($self->is_changed);
190         return 0;
191 }
192
193 sub modify_from_fieldmapper {
194         my $obj = shift;
195         my $fm = shift;
196
197         $log->debug("Modifying object using fieldmapper", DEBUG);
198
199         my $class = ref($obj) || $obj;
200
201         if (!ref($obj)) {
202                 $obj = $class->retrieve($fm);
203                 unless ($obj) {
204                         $log->debug("Rretrieve using $fm (".$fm->id.") failed!", ERROR);
205                         throw OpenSRF::EX::WARN ("No $class with id of ".$fm->id."!!");
206                 }
207
208         }
209
210         my %hash = map { defined $fm->$_ ?
211                                 ($_ => $fm->$_) :
212                                 ()
213                         } $fm->real_fields;
214
215         my $au = $obj->autoupdate;
216         $obj->autoupdate(0);
217         
218         for my $field ( keys %hash ) {
219                 $obj->$field( $hash{$field} ) if ($obj->$field ne $hash{$field});
220                 $log->debug("Setting field $field on $obj to $hash{$field}",INTERNAL);
221         }
222
223         if ($class->find_column( 'last_xact_id' ) and $obj->is_changed) {
224                 my $xact_id = $obj->current_xact_id;
225                 throw Error unless ($xact_id);
226                 $obj->last_xact_id( $xact_id );
227         } else {
228                 $obj->autoupdate($au)
229         }
230
231         return $obj;
232 }
233
234
235
236 sub import {
237         return if ($VERSION);
238         #-------------------------------------------------------------------------------
239         actor::user->has_a( home_ou => 'actor::org_unit' );
240         #actor::org_unit->has_a( address => 'actor::address' );
241         #-------------------------------------------------------------------------------
242         actor::org_unit->has_many( users => 'actor::user' );
243         actor::org_unit->has_a( parent_ou => 'actor::org_unit' );
244         actor::org_unit->has_a( ou_type => 'actor::org_unit_type' );
245         #actor::org_unit->has_a( address => 'actor::address' );
246         #-------------------------------------------------------------------------------
247
248         #-------------------------------------------------------------------------------
249         asset::copy->has_a( call_number => 'asset::call_number' );
250         #asset::copy->might_have( metadata => 'asset::copy_metadata' );
251         #-------------------------------------------------------------------------------
252         #asset::copy_metadata->might_have( copy => 'asset::copy' );
253         asset::copy_metadata->has_a( circulating_location => 'actor::org_unit');
254         asset::copy_metadata->has_a( hold_radius => 'actor::org_unit_type');
255         #-------------------------------------------------------------------------------
256         asset::call_number->has_a( record => 'biblio::record_entry' );
257         asset::call_number->has_many( copies => 'asset::copy' );
258         #-------------------------------------------------------------------------------
259         
260
261         #-------------------------------------------------------------------------------
262         biblio::record_note->has_a( record => 'biblio::record_entry' );
263         #-------------------------------------------------------------------------------
264         biblio::record_entry->has_a( creator => 'actor::user' );
265         biblio::record_entry->has_a( editor => 'actor::user' );
266         biblio::record_entry->might_have( mods_entry => 'biblio::record_mods' => qw/mods/ );
267         biblio::record_entry->has_many( notes => 'biblio::record_note' );
268         biblio::record_entry->has_many( nodes => 'biblio::record_node', { order_by => 'intra_doc_id' } );
269         biblio::record_entry->has_many( call_numbers => 'asset::call_number' );
270         
271         # should we have just one field entry per class for each record???? (xslt vs xpath)
272         #biblio::record_entry->has_a( title_field_entries => 'metabib::title_field_entry' );
273         #biblio::record_entry->has_a( author_field_entries => 'metabib::author_field_entry' );
274         #biblio::record_entry->has_a( subject_field_entries => 'metabib::subject_field_entry' );
275         #biblio::record_entry->has_a( keyword_field_entries => 'metabib::keyword_field_entry' );
276         #-------------------------------------------------------------------------------
277         biblio::record_node->has_a( owner_doc => 'biblio::record_entry' );
278         #biblio::record_node->has_a(
279         #       parent_node     => 'biblio::record_node::subnode',
280         #       inflate         => sub { return biblio::record_node::subnode::_load(@_) }
281         #);
282         #-------------------------------------------------------------------------------
283         
284         #-------------------------------------------------------------------------------
285         metabib::metarecord->has_a( master_record => 'biblio::record_entry' );
286         metabib::metarecord->has_many( source_records => [ 'metabib::metarecord_source_map' => 'source_record'] );
287         #-------------------------------------------------------------------------------
288         metabib::title_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
289         metabib::title_field_entry->has_a( field => 'config::metabib_field' );
290         #-------------------------------------------------------------------------------
291         metabib::author_field_entry->has_many( source_records => [ 'metabib::author_field_entry_source_map' => 'source_record'] );
292         metabib::author_field_entry->has_a( field => 'config::metabib_field' );
293         #-------------------------------------------------------------------------------
294         metabib::subject_field_entry->has_many( source_records => [ 'metabib::title_field_entry_source_map' => 'source_record'] );
295         metabib::subject_field_entry->has_a( field => 'config::metabib_field' );
296         #-------------------------------------------------------------------------------
297         metabib::keyword_field_entry->has_many( source_records => [ 'metabib::keyword_field_entry_source_map' => 'source_record'] );
298         metabib::keyword_field_entry->has_a( field => 'config::metabib_field' );
299         #-------------------------------------------------------------------------------
300         metabib::metarecord_source_map->has_a( metarecord => 'metabib::metarecord' );
301         metabib::metarecord_source_map->has_a( source_record => 'biblio::record_entry' );
302         #-------------------------------------------------------------------------------
303
304
305         # should we have just one field entry per class for each record???? (xslt vs xpath)
306         metabib::title_field_entry_source_map->has_a( field_entry => 'metabib::title_field_entry' );
307         metabib::title_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
308         #-------------------------------------------------------------------------------
309         metabib::subject_field_entry_source_map->has_a( field_entry => 'metabib::subject_field_entry' );
310         metabib::subject_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
311         #-------------------------------------------------------------------------------
312         metabib::author_field_entry_source_map->has_a( field_entry => 'metabib::author_field_entry' );
313         metabib::author_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
314         #-------------------------------------------------------------------------------
315         metabib::keyword_field_entry_source_map->has_a( field_entry => 'metabib::keyword_field_entry' );
316         metabib::keyword_field_entry_source_map->has_a( source_record => 'biblio::record_entry' );
317         #-------------------------------------------------------------------------------
318         $VERSION = 1;
319 }
320
321
322 1;