]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm
adding "user_setting" object
[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
18 use vars qw/$fieldmap $VERSION/;
19
20 _init();
21
22 sub publish_fieldmapper {
23         my ($self,$client,$class) = @_;
24
25         return $fieldmap unless (defined $class);
26         return undef unless (exists($$fieldmap{$class}));
27         return {$class => $$fieldmap{$class}};
28 }
29 __PACKAGE__->register_method(
30         api_name        => 'opensrf.open-ils.system.fieldmapper',
31         api_level       => 1,
32         method          => 'publish_fieldmapper',
33 );
34
35 #
36 # To dump the Javascript version of the fieldmapper struct use the command:
37 #
38 #       PERL5LIB=~/cvs/ILS/OpenSRF/src/perlmods/:~/cvs/ILS/Open-ILS/src/perlmods/ GEN_JS=1 perl -MOpenILS::Utils::Fieldmapper -e 'print "\n";'
39 #
40 # ... adjusted for your CVS sandbox, of course.
41 #
42
43 sub classes {
44         return () unless (defined $fieldmap);
45         return keys %$fieldmap;
46 }
47
48 sub _init {
49         return if (keys %$fieldmap);
50
51         $fieldmap = 
52         {
53                 'Fieldmapper::action::survey'                   => { hint               => 'asv',
54                                                                      proto_fields       => { questions  => 1,
55                                                                                              responses  => 1 } },
56                 'Fieldmapper::action::survey_question'          => { hint               => 'asvq',
57                                                                      proto_fields       => { answers    => 1,
58                                                                                              responses  => 1 } },
59                 'Fieldmapper::action::survey_answer'            => { hint               => 'asva',
60                                                                      proto_fields       => { responses => 1 } },
61                 'Fieldmapper::action::survey_response'          => { hint               => 'asvr'  },
62                 'Fieldmapper::action::circulation'              => { hint               => 'circ',
63                                                                      proto_fields       => {} },
64                 'Fieldmapper::actor::user'                      => { hint               => 'au',
65                                                                      proto_fields       => { cards              => 1,
66                                                                                              survey_responses   => 1,
67                                                                                              stat_cat_entries   => 1,
68                                                                                              checkouts          => 1,
69                                                                                              hold_requests      => 1,
70                                                                                              settings           => 1,
71                                                                                              addresses          => 1 } },
72                 'Fieldmapper::actor::user_setting'              => { hint => 'aus'    },
73                 'Fieldmapper::actor::user_address'              => { hint => 'aua'    },
74                 'Fieldmapper::actor::org_address'               => { hint => 'aoa'    },
75                 'Fieldmapper::actor::profile'                   => { hint => 'ap'    },
76                 'Fieldmapper::actor::card'                      => { hint => 'ac'    },
77                 'Fieldmapper::config::standing'                 => { hint => 'cst'   },
78                 'Fieldmapper::config::copy_status'              => { hint => 'ccs'   },
79                 'Fieldmapper::actor::stat_cat'                  => { hint               => 'actsc',
80                                                                      proto_fields       => { entries => 1 } },
81                 'Fieldmapper::actor::stat_cat_entry'            => { hint => 'actsce'    },
82                 'Fieldmapper::actor::stat_cat_entry_user_map'   => { hint => 'actscecm'  },
83                 'Fieldmapper::actor::org_unit'                  => { hint               => 'aou',
84                                                                      proto_fields       => { children => 1 } },
85                 'Fieldmapper::actor::org_unit_type'             => { hint               => 'aout',
86                                                                      proto_fields       => { children => 1 } },
87                 
88                 'Fieldmapper::biblio::record_node'              => { hint               => 'brn',
89                                                                      virtual            => 1,
90                                                                      proto_fields       => { children           => 1,
91                                                                                              id                 => 1,
92                                                                                              owner_doc          => 1,
93                                                                                              intra_doc_id       => 1,
94                                                                                              parent_node        => 1,
95                                                                                              node_type          => 1,
96                                                                                              namespace_uri      => 1,
97                                                                                              name               => 1,
98                                                                                              value              => 1,
99                                                                                            } },
100
101                 'Fieldmapper::metabib::virtual_record'          => { hint               => 'mvr',
102                                                                      virtual            => 1,
103                                                                      proto_fields       => { title              => 1,
104                                                                                              author             => 1,
105                                                                                              doc_id             => 1,
106                                                                                              doc_type           => 1,
107                                                                                              isbn               => 1,
108                                                                                              pubdate            => 1,
109                                                                                              publisher          => 1,
110                                                                                              tcn                => 1,
111                                                                                              subject            => 1,
112                                                                                              types_of_resource  => 1,
113                                                                                              call_numbers       => 1,
114                                                                                                           edition       => 1,
115                                                                                                           online_loc    => 1,
116                                                                                                           synopsis      => 1,
117                                                                                              copy_count         => 1,
118                                                                                              series             => 1,
119                                                                                              serials            => 1,
120                                                                                            } },
121
122                 'Fieldmapper::biblio::record_entry'             => { hint               => 'bre',
123                                                                      proto_fields       => { call_numbers => 1,
124                                                                                              fixed_fields => 1 } },
125                 #'Fieldmapper::biblio::record_marc'             => { hint => 'brx'  }, # now it's inside record_entry
126
127                 'Fieldmapper::money::payment'                   => { hint => 'mp'  },
128                 'Fieldmapper::money::cash_payment'              => { hint => 'mcp'  },
129                 'Fieldmapper::money::check_payment'             => { hint => 'mckp'  },
130                 'Fieldmapper::money::credit_payment'            => { hint => 'mcrp'  },
131                 'Fieldmapper::money::credit_card_payment'       => { hint => 'mccp'  },
132                 'Fieldmapper::money::forgive_payment'           => { hint => 'mfp'  },
133                 'Fieldmapper::money::work_payment'              => { hint => 'mwp'  },
134
135                 'Fieldmapper::money::billing'                   => { hint => 'mb'  },
136                 'Fieldmapper::money::billable_transaction'      => { hint => 'mbt'  },
137
138                 'Fieldmapper::money::user_summary'              => { hint       => 'mus',
139                                                                      readonly   => 1 },
140
141                 'Fieldmapper::money::billable_transaction_summary'      => { hint       => 'mbts',
142                                                                              readonly   => 1 },
143
144                 'Fieldmapper::config::identification_type'      => { hint => 'cit'  },
145                 'Fieldmapper::config::bib_source'               => { hint => 'cbs'  },
146                 'Fieldmapper::config::metabib_field'            => { hint => 'cmf'  },
147                 'Fieldmapper::config::rules::recuring_fine'     => { hint => 'crrf'  },
148                 'Fieldmapper::config::rules::circ_duration'     => { hint => 'crcd'  },
149                 'Fieldmapper::config::rules::max_fine'          => { hint => 'crmf'  },
150
151                 'Fieldmapper::metabib::metarecord'              => { hint => 'mmr'  },
152                 'Fieldmapper::metabib::title_field_entry'       => { hint => 'mtfe' },
153                 'Fieldmapper::metabib::author_field_entry'      => { hint => 'mafe' },
154                 'Fieldmapper::metabib::subject_field_entry'     => { hint => 'msfe' },
155                 'Fieldmapper::metabib::keyword_field_entry'     => { hint => 'mkfe' },
156                 'Fieldmapper::metabib::series_field_entry'      => { hint => 'msefe' },
157                 'Fieldmapper::metabib::full_rec'                => { hint => 'mfr'  },
158                 'Fieldmapper::metabib::record_descriptor'       => { hint => 'mrd'  },
159                 'Fieldmapper::metabib::metarecord_source_map'   => { hint => 'mmrsm'},
160
161                 'Fieldmapper::asset::copy'                      => { hint               => 'acp',
162                                                                      proto_fields       => { stat_cat_entries => 1 } },
163                 'Fieldmapper::asset::stat_cat'                  => { hint               => 'asc',
164                                                                      proto_fields       => { entries => 1 } },
165                 'Fieldmapper::asset::stat_cat_entry'            => { hint => 'asce'    },
166                 'Fieldmapper::asset::stat_cat_entry_copy_map'   => { hint => 'ascecm'  },
167                 'Fieldmapper::asset::copy_note'                 => { hint => 'acpn'    },
168                 'Fieldmapper::asset::copy_location'             => { hint => 'acpl'    },
169                 'Fieldmapper::asset::call_number'               => { hint               => 'acn',
170                                                                      proto_fields       => { copies => 1 } },
171                 'Fieldmapper::asset::call_number_note'          => { hint => 'acnn'    },
172
173                 'Fieldmapper::permission::perm_list'            => { hint => 'ppl'    },
174                 'Fieldmapper::permission::grp_tree'             => { hint => 'pgt'    },
175                 'Fieldmapper::permission::usr_grp_map'          => { hint => 'pugm'   },
176                 'Fieldmapper::permission::usr_perm_map'         => { hint => 'pupm'   },
177                 'Fieldmapper::permission::grp_perm_map'         => { hint => 'pgpm'   },
178                 'Fieldmapper::action::hold_request'             => { hint => 'ahr'   },
179                 'Fieldmapper::action::hold_notification'        => { hint => 'ahn'   },
180                 'Fieldmapper::action::hold_copy_map'            => { hint => 'ahcm'   },
181                 'Fieldmapper::action::hold_transit_copy'        => { hint => 'ahtc'   },
182
183
184                 'Fieldmapper::ex'                               => { hint           => 'ex',
185                                                                      virtual        => 1,
186                                                                      proto_fields   => {
187                                                                         err_msg  => 1,
188                                                                         type     => 1,
189                                                                      } },
190
191
192                 'Fieldmapper::perm_ex'                          => { hint           => 'perm_ex',
193                                                                      virtual        => 1,
194                                                                      proto_fields   => {
195                                                                         err_msg => 1,
196                                                                         type    => 1,
197                                                                      } },
198
199
200       
201         };
202
203         #-------------------------------------------------------------------------------
204         # Now comes the evil!  Generate classes
205
206         for my $pkg ( __PACKAGE__->classes ) {
207                 (my $cdbi = $pkg) =~ s/^Fieldmapper:://o;
208
209                 eval <<"                PERL";
210                         package $pkg;
211                         use base 'Fieldmapper';
212                 PERL
213
214                 my $pos = 0;
215                 for my $vfield ( qw/isnew ischanged isdeleted/ ) {
216                         $$fieldmap{$pkg}{fields}{$vfield} = { position => $pos, virtual => 1 };
217                         $pos++;
218                 }
219
220                 if (exists $$fieldmap{$pkg}{proto_fields}) {
221                         for my $pfield ( sort keys %{ $$fieldmap{$pkg}{proto_fields} } ) {
222                                 $$fieldmap{$pkg}{fields}{$pfield} = { position => $pos, virtual => $$fieldmap{$pkg}{proto_fields}{$pfield} };
223                                 $pos++;
224                         }
225                 }
226
227                 unless ( $$fieldmap{$pkg}{virtual} ) {
228                         $$fieldmap{$pkg}{cdbi} = $cdbi;
229                         for my $col ( sort $cdbi->columns('All') ) {
230                                 $$fieldmap{$pkg}{fields}{$col} = { position => $pos, virtual => 0 };
231                                 $pos++;
232                         }
233                 }
234
235                 JSON->register_class_hint(
236                         hint => $pkg->json_hint,
237                         name => $pkg,
238                         type => 'array',
239                 );
240
241         }
242 }
243
244 sub new {
245         my $self = shift;
246         my $value = shift;
247         $value = [] unless (defined $value);
248         return bless $value => $self->class_name;
249 }
250
251 sub decast {
252         my $self = shift;
253         return [ @$self ];
254 }
255
256 sub DESTROY {}
257
258 sub AUTOLOAD {
259         my $obj = shift;
260         my $value = shift;
261         (my $field = $AUTOLOAD) =~ s/^.*://o;
262         my $class_name = $obj->class_name;
263
264         my $fpos = $field;
265         $fpos  =~ s/^clear_//og ;
266
267         my $pos = $$fieldmap{$class_name}{fields}{$fpos}{position};
268
269         if ($field =~ /^clear_/o) {
270                 {       no strict 'subs';
271                         *{$obj->class_name."::$field"} = sub {
272                                 my $self = shift;
273                                 $self->[$pos] = undef;
274                                 return 1;
275                         };
276                 }
277                 return $obj->$field();
278         }
279
280         die "No field by the name $field in $class_name!"
281                 unless (exists $$fieldmap{$class_name}{fields}{$field} && defined($pos));
282
283
284         {       no strict 'subs';
285                 *{$obj->class_name."::$field"} = sub {
286                         my $self = shift;
287                         my $new_val = shift;
288                         $self->[$pos] = $new_val if (defined $new_val);
289                         return $self->[$pos];
290                 };
291         }
292         return $obj->$field($value);
293 }
294
295 sub class_name {
296         my $class_name = shift;
297         return ref($class_name) || $class_name;
298 }
299
300 sub real_fields {
301         my $self = shift;
302         my $class_name = $self->class_name;
303         my $fields = $$fieldmap{$class_name}{fields};
304
305         my @f = grep {
306                         !$$fields{$_}{virtual}
307                 } sort {$$fields{$a}{position} <=> $$fields{$b}{position}} keys %$fields;
308
309         return @f;
310 }
311
312 sub properties {
313         my $self = shift;
314         my $class_name = $self->class_name;
315         return keys %{$$fieldmap{$class_name}{fields}};
316 }
317
318 sub clone {
319         my $self = shift;
320         return $self->new( [@$self] );
321 }
322
323 sub api_level {
324         my $self = shift;
325         return $fieldmap->{$self->class_name}->{api_level};
326 }
327
328 sub cdbi {
329         my $self = shift;
330         return $fieldmap->{$self->class_name}->{cdbi};
331 }
332
333 sub is_virtual {
334         my $self = shift;
335         my $field = shift;
336         return $fieldmap->{$self->class_name}->{proto_fields}->{$field} if ($field);
337         return $fieldmap->{$self->class_name}->{virtual};
338 }
339
340 sub is_readonly {
341         my $self = shift;
342         my $field = shift;
343         return $fieldmap->{$self->class_name}->{readonly};
344 }
345
346 sub json_hint {
347         my $self = shift;
348         return $fieldmap->{$self->class_name}->{hint};
349 }
350
351
352 1;