]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm
adding collections related stuff everywhere...
[working/Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Utils / Fieldmapper.pm
1 package Fieldmapper;
2 use JSON;
3 use Data::Dumper;
4 use base 'OpenSRF::Application';
5
6 use OpenSRF::Utils::Logger;
7 my $log = 'OpenSRF::Utils::Logger';
8
9 use OpenILS::Application::Storage::CDBI;
10 use OpenILS::Application::Storage::CDBI::actor;
11 use OpenILS::Application::Storage::CDBI::action;
12 use OpenILS::Application::Storage::CDBI::asset;
13 use OpenILS::Application::Storage::CDBI::biblio;
14 use OpenILS::Application::Storage::CDBI::config;
15 use OpenILS::Application::Storage::CDBI::metabib;
16 use OpenILS::Application::Storage::CDBI::money;
17 use OpenILS::Application::Storage::CDBI::container;
18 use OpenILS::Application::Storage::CDBI::config;
19
20 use vars qw/$fieldmap $VERSION/;
21
22 _init();
23
24 sub publish_fieldmapper {
25         my ($self,$client,$class) = @_;
26
27         return $fieldmap unless (defined $class);
28         return undef unless (exists($$fieldmap{$class}));
29         return {$class => $$fieldmap{$class}};
30 }
31 __PACKAGE__->register_method(
32         api_name        => 'opensrf.open-ils.system.fieldmapper',
33         api_level       => 1,
34         method          => 'publish_fieldmapper',
35 );
36
37 #
38 # To dump the Javascript version of the fieldmapper struct use the command:
39 #
40 #       PERL5LIB=~/cvs/ILS/OpenSRF/src/perlmods/:~/cvs/ILS/Open-ILS/src/perlmods/ GEN_JS=1 perl -MOpenILS::Utils::Fieldmapper -e 'print "\n";'
41 #
42 # ... adjusted for your CVS sandbox, of course.
43 #
44
45 sub classes {
46         return () unless (defined $fieldmap);
47         return keys %$fieldmap;
48 }
49
50 sub _init {
51         return if (keys %$fieldmap);
52
53         $fieldmap = 
54         {
55                 'Fieldmapper::container::user_bucket'           => { hint => 'cub',
56                                                                      proto_fields       => { items => 1 } },
57                 'Fieldmapper::container::copy_bucket'           => { hint => 'ccb',
58                                                                      proto_fields       => { items => 1 } },
59                 'Fieldmapper::container::call_number_bucket'    => { hint => 'ccnb',
60                                                                      proto_fields       => { items => 1 } },
61                 'Fieldmapper::container::biblio_record_entry_bucket'            => { hint => 'cbreb',
62                                                                                      proto_fields       => { items => 1 } },
63
64                 'Fieldmapper::container::user_bucket_item'              => { hint => 'cubi'   },
65                 'Fieldmapper::container::copy_bucket_item'              => { hint => 'ccbi'   },
66                 'Fieldmapper::container::call_number_bucket_item'       => { hint => 'ccnbi'   },
67                 'Fieldmapper::container::biblio_record_entry_bucket_item'               => { hint => 'cbrebi'   },
68
69                 'Fieldmapper::action::in_house_use'             => { hint => 'aihu'   },
70                 'Fieldmapper::action::non_cataloged_circulation'=> { hint => 'ancc'   },
71
72                 'Fieldmapper::action::survey'                   => { hint               => 'asv',
73                                                                      proto_fields       => { questions  => 1,
74                                                                                              responses  => 1 } },
75                 'Fieldmapper::action::survey_question'          => { hint               => 'asvq',
76                                                                      proto_fields       => { answers    => 1,
77                                                                                              responses  => 1 } },
78                 'Fieldmapper::action::survey_answer'            => { hint               => 'asva',
79                                                                      proto_fields       => { responses => 1 } },
80                 'Fieldmapper::action::survey_response'          => { hint               => 'asvr'  },
81                 'Fieldmapper::action::circulation'              => { hint               => 'circ',
82                                                                      proto_fields       => {} },
83
84                 'Fieldmapper::action::open_circulation'         => { hint       => 'aoc',
85                                                                      readonly   => 1 },
86
87                 'Fieldmapper::actor::workstation'               => { hint       => 'aws' },
88
89                 'Fieldmapper::actor::user'                      => { hint               => 'au',
90                                                                      proto_fields       => { cards              => 1,
91                                                                                              survey_responses   => 1,
92                                                                                              stat_cat_entries   => 1,
93                                                                                              checkouts          => 1,
94                                                                                              wsid               => 1,
95                                                                                              ws_ou              => 1,
96                                                                                              hold_requests      => 1,
97                                                                                              settings           => 1,
98                                                                                              permissions        => 1,
99                                                                                              standing_penalties => 1,
100                                                                                              addresses          => 1 } },
101                 'Fieldmapper::actor::usr_note'                  => { hint => 'aun'    },
102                 'Fieldmapper::actor::user_setting'              => { hint => 'aus'    },
103                 'Fieldmapper::actor::user_standing_penalty'     => { hint => 'ausp'    },
104                 'Fieldmapper::actor::org_unit_setting'          => { hint => 'aous'    },
105                 'Fieldmapper::actor::user_address'              => { hint => 'aua'    },
106                 'Fieldmapper::actor::org_address'               => { hint => 'aoa'    },
107                 'Fieldmapper::actor::profile'                   => { hint => 'ap'    },
108                 'Fieldmapper::actor::card'                      => { hint => 'ac'    },
109                 'Fieldmapper::actor::stat_cat'                  => { hint               => 'actsc',
110                                                                      proto_fields       => { entries => 1 } },
111                 'Fieldmapper::actor::stat_cat_entry'            => { hint => 'actsce'    },
112                 'Fieldmapper::actor::stat_cat_entry_user_map'   => { hint => 'actscecm'  },
113                 'Fieldmapper::actor::org_unit'                  => { hint               => 'aou',
114                                                                      proto_fields       => { children => 1 } },
115                 'Fieldmapper::actor::org_unit::closed_date'     => { hint => 'aoucd'    },
116                 'Fieldmapper::actor::org_unit::hours_of_operation'      => { hint => 'aouhoo'    },
117                 'Fieldmapper::actor::org_unit_type'             => { hint               => 'aout',
118                                                                      proto_fields       => { children => 1 } },
119                 
120                 'Fieldmapper::biblio::record_node'              => { hint               => 'brn',
121                                                                      virtual            => 1,
122                                                                      proto_fields       => { children           => 1,
123                                                                                              id                 => 1,
124                                                                                              owner_doc          => 1,
125                                                                                              intra_doc_id       => 1,
126                                                                                              parent_node        => 1,
127                                                                                              node_type          => 1,
128                                                                                              namespace_uri      => 1,
129                                                                                              name               => 1,
130                                                                                              value              => 1,
131                                                                                            } },
132
133                 'Fieldmapper::metabib::virtual_record'          => { hint               => 'mvr',
134                                                                      virtual            => 1,
135                                                                      proto_fields       => { title              => 1,
136                                                                                              author             => 1,
137                                                                                              doc_id             => 1,
138                                                                                              doc_type           => 1,
139                                                                                              isbn               => 1,
140                                                                                              pubdate            => 1,
141                                                                                              publisher          => 1,
142                                                                                              tcn                => 1,
143                                                                                              subject            => 1,
144                                                                                              types_of_resource  => 1,
145                                                                                              call_numbers       => 1,
146                                                                                                           edition       => 1,
147                                                                                                           online_loc    => 1,
148                                                                                                           synopsis      => 1,
149                                                                                                           physical_description  => 1,
150                                                                                                           toc => 1,
151                                                                                              copy_count         => 1,
152                                                                                              series             => 1,
153                                                                                              serials            => 1,
154                                                                                            } },
155
156                 'Fieldmapper::authority::record_entry'          => { hint               => 'are', },
157                 'Fieldmapper::authority::record_note'           => { hint               => 'arn', },
158                 'Fieldmapper::biblio::record_note'              => { hint               => 'bren', },
159                 'Fieldmapper::biblio::record_entry'             => { hint               => 'bre',
160                                                                      proto_fields       => { call_numbers => 1,
161                                                                                              fixed_fields => 1 } },
162                 #'Fieldmapper::biblio::record_marc'             => { hint => 'brx'  }, # now it's inside record_entry
163
164                 'Fieldmapper::money::payment'                   => { hint => 'mp',
165                                                                      readonly   => 1 },
166
167                 'Fieldmapper::money::cash_payment'              => { hint => 'mcp'  },
168                 'Fieldmapper::money::check_payment'             => { hint => 'mckp'  },
169                 'Fieldmapper::money::credit_payment'            => { hint => 'mcrp'  },
170                 'Fieldmapper::money::credit_card_payment'       => { hint => 'mccp'  },
171                 'Fieldmapper::money::forgive_payment'           => { hint => 'mfp'  },
172                 'Fieldmapper::money::work_payment'              => { hint => 'mwp'  },
173                 'Fieldmapper::money::collections_tracker'       => { hint => 'mct'  },
174
175                 'Fieldmapper::money::billing'                   => { hint => 'mb'  },
176                 'Fieldmapper::money::billable_transaction'      => { hint => 'mbt'  },
177                 'Fieldmapper::money::grocery'                   => { hint => 'mg'  },
178
179                 'Fieldmapper::money::open_user_summary'         => { hint       => 'mous',
180                                                                      readonly   => 1 },
181                 'Fieldmapper::money::user_summary'              => { hint       => 'mus',
182                                                                      readonly   => 1 },
183
184                 'Fieldmapper::money::open_user_circulation_summary'     => { hint       => 'moucs',
185                                                                              readonly   => 1 },
186                 'Fieldmapper::money::user_circulation_summary'  => { hint       => 'mucs',
187                                                                      readonly   => 1 },
188
189                 'Fieldmapper::money::open_billable_transaction_summary' => { hint       => 'mobts',
190                                                                              readonly   => 1 },
191                 'Fieldmapper::money::billable_transaction_summary'      => { hint       => 'mbts',
192                                                                              readonly   => 1 },
193
194                 'Fieldmapper::config::identification_type'      => { hint => 'cit'  },
195                 'Fieldmapper::config::bib_source'               => { hint => 'cbs'  },
196                 'Fieldmapper::config::metabib_field'            => { hint => 'cmf'  },
197                 'Fieldmapper::config::rules::age_hold_protect'  => { hint => 'crahp'  },
198                 'Fieldmapper::config::rules::recuring_fine'     => { hint => 'crrf'  },
199                 'Fieldmapper::config::rules::circ_duration'     => { hint => 'crcd'  },
200                 'Fieldmapper::config::rules::max_fine'          => { hint => 'crmf'  },
201                 'Fieldmapper::config::non_cataloged_type'       => { hint => 'cnct'   },
202                 'Fieldmapper::config::standing'                 => { hint => 'cst'   },
203                 'Fieldmapper::config::copy_status'              => { hint => 'ccs'   },
204                 'Fieldmapper::config::net_access_level'         => { hint => 'cnal'   },
205
206                 'Fieldmapper::config::audience_map'             => { hint       => 'cam',
207                                                                      readonly   => 1 },
208                 'Fieldmapper::config::language_map'             => { hint       => 'clm',
209                                                                      readonly   => 1 },
210                 'Fieldmapper::config::item_form_map'            => { hint       => 'cifm',
211                                                                      readonly   => 1 },
212                 'Fieldmapper::config::item_type_map'            => { hint       => 'citm',
213                                                                      readonly   => 1 },
214                 'Fieldmapper::config::lit_form_map'             => { hint       => 'clfm',
215                                                                      readonly   => 1 },
216
217                 'Fieldmapper::authority::full_rec'              => { hint => 'afr'  },
218                 'Fieldmapper::authority::record_descriptor'     => { hint => 'ard'  },
219
220                 'Fieldmapper::metabib::metarecord'              => { hint => 'mmr'  },
221                 'Fieldmapper::metabib::title_field_entry'       => { hint => 'mtfe' },
222                 'Fieldmapper::metabib::author_field_entry'      => { hint => 'mafe' },
223                 'Fieldmapper::metabib::subject_field_entry'     => { hint => 'msfe' },
224                 'Fieldmapper::metabib::keyword_field_entry'     => { hint => 'mkfe' },
225                 'Fieldmapper::metabib::series_field_entry'      => { hint => 'msefe' },
226                 'Fieldmapper::metabib::full_rec'                => { hint => 'mfr'  },
227                 'Fieldmapper::metabib::record_descriptor'       => { hint => 'mrd'  },
228                 'Fieldmapper::metabib::metarecord_source_map'   => { hint => 'mmrsm'},
229
230                 'Fieldmapper::asset::copy'                      => { hint               => 'acp',
231                                                                      proto_fields       => { stat_cat_entries => 1 } },
232                 'Fieldmapper::asset::stat_cat'                  => { hint               => 'asc',
233                                                                      proto_fields       => { entries => 1 } },
234                 'Fieldmapper::asset::stat_cat_entry'            => { hint => 'asce'    },
235                 'Fieldmapper::asset::stat_cat_entry_copy_map'   => { hint => 'ascecm'  },
236                 'Fieldmapper::asset::copy_note'                 => { hint => 'acpn'    },
237                 'Fieldmapper::asset::copy_location'             => { hint => 'acpl'    },
238                 'Fieldmapper::asset::call_number'               => { hint               => 'acn',
239                                                                      proto_fields       => { copies => 1 } },
240                 'Fieldmapper::asset::call_number_note'          => { hint => 'acnn'    },
241
242                 'Fieldmapper::permission::perm_list'            => { hint => 'ppl'    },
243                 'Fieldmapper::permission::grp_tree'             => { hint => 'pgt', proto_fields => { children => 1 } },
244                 'Fieldmapper::permission::usr_grp_map'          => { hint => 'pugm'   },
245                 'Fieldmapper::permission::usr_perm_map'         => { hint => 'pupm'   },
246                 'Fieldmapper::permission::grp_perm_map'         => { hint => 'pgpm'   },
247                 'Fieldmapper::action::hold_request'             => { hint => 'ahr', proto_fields => { status => 1, transit => 1 } },
248                 'Fieldmapper::action::hold_notification'        => { hint => 'ahn'    },
249                 'Fieldmapper::action::hold_copy_map'            => { hint => 'ahcm'   },
250                 'Fieldmapper::action::hold_transit_copy'        => { hint => 'ahtc'   },
251                 'Fieldmapper::action::transit_copy'             => { hint => 'atc'    },
252                 'Fieldmapper::action::unfulfilled_hold_list'    => { hint => 'aufh'   },
253
254
255                 'Fieldmapper::ex'                               => { hint           => 'ex',
256                                                                      virtual        => 1,
257                                                                      proto_fields   => {
258                                                                         err_msg  => 1,
259                                                                         type     => 1,
260                                                                      } },
261
262
263                 'Fieldmapper::perm_ex'                          => { hint           => 'perm_ex',
264                                                                      virtual        => 1,
265                                                                      proto_fields   => {
266                                                                         err_msg => 1,
267                                                                         type    => 1,
268                                                                      } },
269
270
271       
272         };
273
274         #-------------------------------------------------------------------------------
275         # Now comes the evil!  Generate classes
276
277         for my $pkg ( __PACKAGE__->classes ) {
278                 (my $cdbi = $pkg) =~ s/^Fieldmapper:://o;
279
280                 eval <<"                PERL";
281                         package $pkg;
282                         use base 'Fieldmapper';
283                 PERL
284
285                 my $pos = 0;
286                 for my $vfield ( qw/isnew ischanged isdeleted/ ) {
287                         $$fieldmap{$pkg}{fields}{$vfield} = { position => $pos, virtual => 1 };
288                         $pos++;
289                 }
290
291                 if (exists $$fieldmap{$pkg}{proto_fields}) {
292                         for my $pfield ( sort keys %{ $$fieldmap{$pkg}{proto_fields} } ) {
293                                 $$fieldmap{$pkg}{fields}{$pfield} = { position => $pos, virtual => $$fieldmap{$pkg}{proto_fields}{$pfield} };
294                                 $pos++;
295                         }
296                 }
297
298                 unless ( $$fieldmap{$pkg}{virtual} ) {
299                         $$fieldmap{$pkg}{cdbi} = $cdbi;
300                         for my $col ( sort $cdbi->columns('Essential') ) {
301                                 $$fieldmap{$pkg}{fields}{$col} = { position => $pos, virtual => 0 };
302                                 $pos++;
303                         }
304                 }
305
306                 JSON->register_class_hint(
307                         hint => $pkg->json_hint,
308                         name => $pkg,
309                         type => 'array',
310                 );
311
312         }
313 }
314
315 sub new {
316         my $self = shift;
317         my $value = shift;
318         $value = [] unless (defined $value);
319         return bless $value => $self->class_name;
320 }
321
322 sub decast {
323         my $self = shift;
324         return [ @$self ];
325 }
326
327 sub DESTROY {}
328
329 sub AUTOLOAD {
330         my $obj = shift;
331         my $value = shift;
332         (my $field = $AUTOLOAD) =~ s/^.*://o;
333         my $class_name = $obj->class_name;
334
335         my $fpos = $field;
336         $fpos  =~ s/^clear_//og ;
337
338         my $pos = $$fieldmap{$class_name}{fields}{$fpos}{position};
339
340         if ($field =~ /^clear_/o) {
341                 {       no strict 'subs';
342                         *{$obj->class_name."::$field"} = sub {
343                                 my $self = shift;
344                                 $self->[$pos] = undef;
345                                 return 1;
346                         };
347                 }
348                 return $obj->$field();
349         }
350
351         die "No field by the name $field in $class_name!"
352                 unless (exists $$fieldmap{$class_name}{fields}{$field} && defined($pos));
353
354
355         {       no strict 'subs';
356                 *{$obj->class_name."::$field"} = sub {
357                         my $self = shift;
358                         my $new_val = shift;
359                         $self->[$pos] = $new_val if (defined $new_val);
360                         return $self->[$pos];
361                 };
362         }
363         return $obj->$field($value);
364 }
365
366 sub class_name {
367         my $class_name = shift;
368         return ref($class_name) || $class_name;
369 }
370
371 sub real_fields {
372         my $self = shift;
373         my $class_name = $self->class_name;
374         my $fields = $$fieldmap{$class_name}{fields};
375
376         my @f = grep {
377                         !$$fields{$_}{virtual}
378                 } sort {$$fields{$a}{position} <=> $$fields{$b}{position}} keys %$fields;
379
380         return @f;
381 }
382
383 sub has_field {
384         my $self = shift;
385         my $field = shift;
386         my $class_name = $self->class_name;
387         return 1 if grep { $_ eq $field } keys %{$$fieldmap{$class_name}{fields}};
388         return 0;
389 }
390
391 sub properties {
392         my $self = shift;
393         my $class_name = $self->class_name;
394         return keys %{$$fieldmap{$class_name}{fields}};
395 }
396
397 sub clone {
398         my $self = shift;
399         return $self->new( [@$self] );
400 }
401
402 sub api_level {
403         my $self = shift;
404         return $fieldmap->{$self->class_name}->{api_level};
405 }
406
407 sub cdbi {
408         my $self = shift;
409         return $fieldmap->{$self->class_name}->{cdbi};
410 }
411
412 sub is_virtual {
413         my $self = shift;
414         my $field = shift;
415         return $fieldmap->{$self->class_name}->{proto_fields}->{$field} if ($field);
416         return $fieldmap->{$self->class_name}->{virtual};
417 }
418
419 sub is_readonly {
420         my $self = shift;
421         my $field = shift;
422         return $fieldmap->{$self->class_name}->{readonly};
423 }
424
425 sub json_hint {
426         my $self = shift;
427         return $fieldmap->{$self->class_name}->{hint};
428 }
429
430
431 1;