2 use OpenSRF::Utils::JSON;
4 use base 'OpenSRF::Application';
5 use OpenSRF::Utils::Logger;
6 use OpenSRF::Utils::SettingsClient;
10 my $log = 'OpenSRF::Utils::Logger';
12 use vars qw/$fieldmap $VERSION/;
14 sub publish_fieldmapper {
15 my ($self,$client,$class) = @_;
17 return $fieldmap unless (defined $class);
18 return undef unless (exists($$fieldmap{$class}));
19 return {$class => $$fieldmap{$class}};
21 __PACKAGE__->register_method(
22 api_name => 'opensrf.open-ils.system.fieldmapper',
24 method => 'publish_fieldmapper',
28 # To dump the Javascript version of the fieldmapper struct use the command:
30 # PERL5LIB=~/cvs/ILS/OpenSRF/src/perlmods/:~/cvs/ILS/Open-ILS/src/perlmods/ GEN_JS=1 perl -MOpenILS::Utils::Fieldmapper -e 'print "\n";'
32 # ... adjusted for your CVS sandbox, of course.
36 return () unless (defined $fieldmap);
37 return keys %$fieldmap;
45 return if (keys %$fieldmap);
46 return if (!OpenSRF::System->connected && !$args{IDL});
49 my $file = $args{IDL} || OpenSRF::Utils::SettingsClient->new->config_value( 'IDL' );
50 #my $idl = XMLin( $file, ForceArray => 0, KeyAttr => ['name', 'id'], ValueAttr => {link =>'key'} )->{class};
51 my $idl = XMLin( $file, ForceArray => 0, KeyAttr => ['name', 'id', 'field'] )->{class};
53 for my $c ( keys %$idl ) {
54 next unless ($idl->{$c}{'oils_obj:fieldmapper'});
55 my $n = 'Fieldmapper::'.$idl->{$c}{'oils_obj:fieldmapper'};
57 $log->debug("Building Fieldmapper class for [$n] from IDL");
59 $$fieldmap{$n}{hint} = $c;
60 $$fieldmap{$n}{virtual} = ($idl->{$c}{'oils_persist:virtual'} && $idl->{$c}{'oils_persist:virtual'} eq 'true') ? 1 : 0;
61 $$fieldmap{$n}{table} = $idl->{$c}{'oils_persist:tablename'};
62 $$fieldmap{$n}{controller} = [ split ' ', $idl->{$c}{'controller'} ];
63 $$fieldmap{$n}{restrict_primary} = $idl->{$c}{'oils_persist:restrict_primary'};
64 $$fieldmap{$n}{sequence} = $idl->{$c}{fields}{'oils_persist:sequence'};
65 $$fieldmap{$n}{identity} = $idl->{$c}{fields}{'oils_persist:primary'};
67 for my $f ( keys %{ $idl->{$c}{fields}{field} } ) {
68 $$fieldmap{$n}{fields}{$f} =
69 { virtual => ($idl->{$c}{fields}{field}{$f}{'oils_persist:virtual'} eq 'true') ? 1 : 0,
70 position => $idl->{$c}{fields}{field}{$f}{'oils_obj:array_position'},
73 if ($idl->{$c}{fields}{field}{$f}{'reporter:selector'}) {
74 $$fieldmap{$n}{selector} = $idl->{$c}{fields}{field}{$f}{'reporter:selector'};
77 for my $f ( keys %{ $idl->{$c}{links}{link} } ) {
78 $$fieldmap{$n}{links}{$f} =
79 { class => $idl->{$c}{links}{link}{$f}{class},
80 reltype => $idl->{$c}{links}{link}{$f}{reltype},
81 key => $idl->{$c}{links}{link}{$f}{key},
87 #-------------------------------------------------------------------------------
88 # Now comes the evil! Generate classes
90 for my $pkg ( __PACKAGE__->classes ) {
91 (my $cdbi = $pkg) =~ s/^Fieldmapper:://o;
95 use base 'Fieldmapper';
99 for my $vfield ( qw/isnew ischanged isdeleted/ ) {
100 $$fieldmap{$pkg}{fields}{$vfield} = { position => $pos, virtual => 1 };
104 if (exists $$fieldmap{$pkg}{proto_fields}) {
105 for my $pfield ( sort keys %{ $$fieldmap{$pkg}{proto_fields} } ) {
106 $$fieldmap{$pkg}{fields}{$pfield} = { position => $pos, virtual => $$fieldmap{$pkg}{proto_fields}{$pfield} };
111 OpenSRF::Utils::JSON->register_class_hint(
112 hint => $pkg->json_hint,
123 $value = [] unless (defined $value);
124 return bless $value => $self->class_name;
137 (my $field = $AUTOLOAD) =~ s/^.*://o;
138 my $class_name = $obj->class_name;
141 $fpos =~ s/^clear_//og ;
143 my $pos = $$fieldmap{$class_name}{fields}{$fpos}{position};
145 if ($field =~ /^clear_/o) {
147 *{$obj->class_name."::$field"} = sub {
149 $self->[$pos] = undef;
153 return $obj->$field();
156 die "No field by the name $field in $class_name!"
157 unless (exists $$fieldmap{$class_name}{fields}{$field} && defined($pos));
161 *{$obj->class_name."::$field"} = sub {
164 $self->[$pos] = $new_val if (defined $new_val);
165 return $self->[$pos];
168 return $obj->$field($value);
173 return $$fieldmap{$self->class_name}{selector};
178 return $$fieldmap{$self->class_name}{identity};
181 sub RestrictPrimary {
183 return $$fieldmap{$self->class_name}{restrict_primary};
188 return $$fieldmap{$self->class_name}{sequence};
193 return $$fieldmap{$self->class_name}{table};
198 return $$fieldmap{$self->class_name}{controller};
202 my $class_name = shift;
203 return ref($class_name) || $class_name;
208 my $class_name = $self->class_name;
209 my $fields = $$fieldmap{$class_name}{fields};
212 !$$fields{$_}{virtual}
213 } sort {$$fields{$a}{position} <=> $$fields{$b}{position}} keys %$fields;
221 my $class_name = $self->class_name;
222 return 1 if grep { $_ eq $field } keys %{$$fieldmap{$class_name}{fields}};
228 my $class_name = $self->class_name;
229 return keys %{$$fieldmap{$class_name}{fields}};
236 for my $f ($self->properties) {
246 return $self->new( [@$self] );
251 return $fieldmap->{$self->class_name}->{api_level};
256 return $fieldmap->{$self->class_name}->{cdbi};
262 return $fieldmap->{$self->class_name}->{proto_fields}->{$field} if ($field);
263 return $fieldmap->{$self->class_name}->{virtual};
269 return $fieldmap->{$self->class_name}->{readonly};
274 return $fieldmap->{$self->class_name}->{hint};