]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Utils/SpiderMonkey.pm
added retrieve method to return the string value for a given path/key
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Utils / SpiderMonkey.pm
1 package OpenILS::Utils::SpiderMonkey;
2 use strict; use warnings;
3 use OpenSRF::Utils::Logger qw(:logger);
4 use OpenILS::Utils::ScriptRunner;
5 use base 'OpenILS::Utils::ScriptRunner';
6 use JavaScript::SpiderMonkey;
7
8 sub new {
9         my ( $class, %params ) = @_;
10         $class = ref($class) || $class;
11         my $self = { file => $params{file}, libs => $params{libs} };
12         return bless( $self, $class );
13 }
14
15 sub context {
16         my( $self, $context ) = @_;
17         $self->{ctx} = $context if $context;
18         return $self->{ctx};
19 }
20
21 sub init {
22         my $self = shift;
23         my $js = JavaScript::SpiderMonkey->new();
24         $js->init();
25         $js->function_set("perl_print",         sub { print "@_\n"; } );
26         $js->function_set("log_error",          sub { $logger->error(@_); return 1;} );
27         $js->function_set("log_warn",                   sub { $logger->warn(@_); return 1;} );
28         $js->function_set("log_info",                   sub { $logger->info(@_); return 1;} );
29         $js->function_set("log_debug",          sub { $logger->debug(@_); return 1;} );
30         $js->function_set("log_internal",       sub { $logger->internal(@_); return 1;} );
31         $js->function_set("debug",                              sub { $logger->debug(@_); return 1;} );
32         $js->function_set("alert",                              sub { $logger->warn(@_); return 1;} );
33         $self->context($js);
34         $self->load_lib($_) for @{$self->{libs}};
35 }
36
37
38 sub load {
39         my( $self, $filename ) = @_;
40         $self->{file} = $filename;
41 }
42
43 sub run {
44         my $self = shift;
45         my $file = shift() || $self->{file};
46         my $js = $self->context;
47
48         if( ! open(F, $file) ) {
49                 $logger->error("Error opening script file: $file");
50                 return 0;
51         }
52
53         if( ! $js->eval(join("\n", <F>)) ) {
54                 $logger->error("Script ($file) eval failed in SpiderMonkey run: $@");  
55                 return 0;
56         }
57
58         close(F);
59         return 1;
60 }
61
62 sub load_lib { 
63         my( $self, $file ) = @_;
64         $self->run( $file );
65 }
66
67 sub _js_prop_name {
68         my $name = shift;
69         $name =~ s/^.*\.//o;
70         return $name;
71 }
72
73 sub retrieve {
74         my( $self, $key ) = @_;
75         return $self->context->property_get($key);
76 }
77
78 sub insert {
79         my( $self, $key, $val ) = @_;
80         return unless defined($val);
81
82         if (ref($val) =~ /^Fieldmapper/o) {
83                 $self->insert_fm($key, $val);
84         } elsif (ref($val) and $val =~ /ARRAY/o) {
85                 $self->insert_array($key, $val);
86         } elsif (ref($val) and $val =~ /HASH/o) {
87                 $self->insert_hash($key, $val);
88         } elsif (!ref($val)) {
89                 $self->context->property_by_path(
90                         $key, $val,
91                         sub { $val },
92                         sub { my( $k, $v ) = @_; $val = $v; }
93                 );
94         } else {
95                 return 0;
96         }
97
98         return 1;
99 }
100
101 sub insert_fm {
102
103         my( $self, $key, $fm ) = @_;
104         my $ctx = $self->context;
105         return undef unless ($ctx and $key and $fm);
106         my $o = $ctx->object_by_path($key);
107         
108         for my $f ( $fm->properties ) {
109                 my $val = $fm->$f();
110                 if (ref $val) {
111                         $self->insert("$key.$f", $val);
112                 } else {
113                         $ctx->property_by_path(
114                                 "$key.$f",
115                                 $val,
116                                 sub {
117                                         my $k = _js_prop_name(shift());
118                                         $fm->$k();
119                                 }, 
120
121                                 sub {
122                                         my $k = _js_prop_name(shift());
123                                         $fm->ischanged(1);
124                                         $fm->$k(@_);
125                                 }
126                         );
127                 }
128         }
129 }
130
131 sub insert_hash {
132
133         my( $self, $key, $hash ) = @_;
134         my $ctx = $self->context;
135         return undef unless ($ctx and $key and $hash);
136         $ctx->object_by_path($key);
137         
138         for my $k ( keys %$hash ) {
139                 my $v = $hash->{$k};
140                 if (ref $v) {
141                         $self->insert("$key.$k", $v);
142                 } else {
143                         $ctx->property_by_path(
144                                 "$key.$k", $v,
145                                 sub { $hash->{_js_prop_name(shift())} },
146                                 sub { 
147                                         my( $key, $val ) = @_;
148                                         $hash->{_js_prop_name($key)} = $val; }
149                         );
150                 }
151         }
152 }
153
154 sub insert_array {
155
156         my( $self, $key, $array ) = @_;
157         my $ctx = $self->context;
158         return undef unless ($ctx and $key and $array);
159
160         my $a = $ctx->array_by_path($key);
161         
162         my $ind = 0;
163         for my $v ( @$array ) {
164                 if (ref $v) {
165                         my $elobj = $ctx->object_by_path('__tmp_arr_el');
166                         $self->insert('__tmp_arr_el', $v);
167                         $ctx->array_set_element_as_object( $a, $ind, $elobj );
168                 } else {
169                         $ctx->array_set_element( $a, $ind, $v ) if defined($v);
170                 }
171                 $ind++;
172         }
173 }
174
175 1;