]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm
initial single-event firing module
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Trigger / Event.pm
1 package OpenILS::Application::Trigger::Event;
2 use OpenSRF::EX qw/:try/;
3
4 use OpenSRF::Utils::Logger qw/:level/;
5
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Utils::CStoreEditor q/:funcs/;
8 use OpenILS::Application::Trigger::ModRunner;
9
10 my $log = 'OpenSRF::Utils::Logger';
11
12 sub new {
13     my $class = shift;
14     $class = ref($class) || $class;
15
16     my $id = shift;
17     return undef unless ($id);
18
19     my $cstore = new_editor();
20     my $event = $cstore->retrieve_action_trigger_event( $id );
21     return undef unless ($event);
22
23     return bless { id => $id, event => $event, environment => {}, editor => $cstore } => $class;
24 }
25
26 sub cleanup {
27     my $self = shift;
28
29     if (defined $self->reacted) {
30         $self->update_state( 'cleaning');
31         try {
32             my $cleanup = $self->reacted ? $self->definition->cleanup_success : $self->definition->cleanup_failure;
33             $self->cleanedup(
34                 OpenILS::Application::Trigger::ModRunner
35                     ->new( $cleanup, $self->environment )
36                     ->run
37                     ->final_result
38             );
39         } otherwise {
40             $log->error( shift() );
41             $self->update_state( 'error' );
42         };
43
44         $self->cleanedup ?
45             $self->update_state( 'complete' ) :
46             $self->update_state( 'error' );
47
48     } else {
49         $self->{cleanedup} = undef;
50     }
51     return $self;
52 }
53
54 sub react {
55     my $self = shift;
56
57     if ($self->valid) {
58         if ($self->definition->group_field) { # can't react individually to a grouped definition
59             $self->{reacted} = undef;
60         } else {
61             $self->update_state( 'reacting');
62             try {
63                 $self->reacted(
64                     OpenILS::Application::Trigger::ModRunner
65                         ->new( $self->definition->reactor, $self->environment )
66                         ->run
67                         ->final_result
68                 );
69             } otherwise {
70                 $log->error( shift() );
71                 $self->update_state( 'error' );
72             };
73
74             defined $self->reacted ? 
75                 $self->update_state( 'reacted' ) :
76                 $self->update_state( 'error' );
77         }
78     } else {
79         $self->{reacted} = undef;
80     }
81     return $self;
82 }
83
84 sub validate {
85     my $self = shift;
86
87     return $self if (defined $self->valid);
88
89     if ($self->build_environment->environment->{complete}) {
90         $self->update_state( 'validating');
91         try {
92             $self->valid(
93                 OpenILS::Application::Trigger::ModRunner
94                     ->new( $self->definition->validator, $self->environment )
95                     ->run
96                     ->final_result
97             );
98         } otherwise {
99             $log->error( shift() );
100             $self->update_state( 'error' );
101         };
102
103         if (defined $self->valid) {
104             $self->valid ? $self->update_state( 'valid' ) : $self->update_state( 'invalid' );
105         } else {
106             $self->update_state( 'error' );
107         }
108     } else {
109         $self->{valid} = undef
110     }
111
112     return $self;
113 }
114  
115 sub cleanedup {
116     my $self = shift;
117     return undef unless (ref $self);
118
119     my $c = shift;
120     $self->{cleanedup} = $c if (defined $c);
121     return $self->{cleanedup};
122 }
123
124 sub reacted {
125     my $self = shift;
126     return undef unless (ref $self);
127
128     my $r = shift;
129     $self->{reacted} = $r if (defined $r);
130     return $self->{reacted};
131 }
132
133 sub valid {
134     my $self = shift;
135     return undef unless (ref $self);
136
137     my $v = shift;
138     $self->{valid} = $v if (defined $v);
139     return $self->{valid};
140 }
141
142 sub event {
143     my $self = shift;
144     return undef unless (ref $self);
145
146     my $e = shift;
147     $self->{event} = $e if (defined $e);
148     return $self->{event};
149 }
150
151 sub id {
152     my $self = shift;
153     return undef unless (ref $self);
154
155     my $i = shift;
156     $self->{id} = $i if (defined $i);
157     return $self->{id};
158 }
159
160 sub environment {
161     my $self = shift;
162     return undef unless (ref $self);
163
164     my $e = shift;
165     $self->{environment} = $e if (defined $e);
166     return $self->{environment};
167 }
168
169 sub editor {
170     my $self = shift;
171     return undef unless (ref $self);
172
173     my $e = shift;
174     $self->{editor} = $e if (defined $e);
175     return $self->{editor};
176 }
177
178 sub target {
179     my $self = shift;
180     return undef unless (ref $self);
181
182     my $t = shift;
183     $self->{target} = $t if (defined $t);
184     return $self->{target};
185 }
186
187 sub definition {
188     my $self = shift;
189     return undef unless (ref $self);
190
191     my $d = shift;
192     $self->{definition} = $d if (defined $d);
193     return $self->{definition};
194 }
195
196 sub update_state {
197     my $self = shift;
198     return undef unless ($self && ref $self);
199
200     my $state = shift || return undef;
201
202     $self->editor->xact_begin || return undef;
203     $self->event->update_time( 'now' );
204     $self->event->update_process( $$ );
205     $self->event->state( $state );
206     $self->editor->update_action_trigger_event( $self->event );
207     $self->editor->xact_commit || return undef;
208
209 }
210
211 sub build_environment {
212     my $self = shift;
213     return $self if ($self->environment->{complete});
214
215     $self->update_state( 'collecting');
216
217     try {
218         $self->definition( $self->editor->retrieve_action_trigger_event_definition( $self->event->event_def ) );
219     
220         $self->definition->hook( $self->editor->retrieve_action_trigger_hook( $self->definition->hook ) );
221         $self->definition->validator( $self->editor->retrieve_action_trigger_validator( $self->definition->validator ) );
222         $self->definition->reactor( $self->editor->retrieve_action_trigger_reactor( $self->definition->reactor ) );
223         $self->definition->cleanup_success( $self->editor->retrieve_action_trigger_cleanup( $self->definition->cleanup_success ) ) if $self->definition->cleanup_success;
224         $self->definition->cleanup_failure( $self->editor->retrieve_action_trigger_cleanup( $self->definition->cleanup_failure ) ) if $self->definition->cleanup_failure;
225     
226         my $class = $self->_fm_class_by_hint( $self->definition->hook->core_type );
227     
228         my $meth = "retreive_" . $class;
229         $meth =~ s/Fieldmapper:://;
230         $meth =~ s/::/_/;
231     
232         $self->target( $self->editor->$meth( $self->event->target ) );
233         $self->environment->{target} = $self->target;
234         $self->environment->{event} = $self->event->to_bare_hash;
235         $self->environment->{template} = $self->definition->template;
236     
237         my @env_list = $self->editor->search_action_trigger_environment( { event_def => $self->event->event_def } );
238         my @param_list = $self->editor->search_action_trigger_params( { event_def => $self->event->event_def } );
239     
240         $self->environment->{params}{ $_->param } = eval $_->value for ( @param_list );
241     
242         for my $e ( @env_list ) {
243             my (@label, @path);
244             @path = split('.', $e->path) if ($e->path);
245             @label = split('.', $e->label) if ($e->label);
246     
247             my $collector = $e->collector;
248             $self->_object_by_path( $target, $collector, \@label, \@path );
249         }
250     
251         $self->environment->{complete} = 1;
252     } otherwise {
253         $log->error( shift() );
254         $self->update_state( 'error' );
255     };
256
257     $self->environment->{complete} ? 
258         $self->update_state( 'collected' ) :
259         $self->update_state( 'error' );
260
261     return $self;
262 }
263
264 sub _fm_class_by_hint {
265     my $self = shift;
266     my $hint = shift;
267
268     my ($class) = grep {
269         Fieldmapper->publish_fieldmapper->{$_}->{hint} eq $hint
270     } keys %{ Fieldmapper->publish_fieldmapper };
271
272     return $class;
273 }
274
275 sub _object_by_path {
276     my $self = shift;
277     my $context = shift;
278     my $collector = shift;
279     my $label = shift;
280     my $path = shift;
281
282     my $step = shift(@$path);
283     
284     my $fhint = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{class};
285     my $fclass = $self->_fm_class_by_hint( $fhint );
286
287     my $ffield = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{key};
288     my $rtype = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{reltype};
289
290     my $meth = 'retrieve_';
291     my $multi = 0;
292     my $lfield = $step;
293     if ($rtype eq 'has_many') {
294         $meth = 'search_';
295         $multi = 1;
296         $lfield = $context->Identity;
297     }
298
299     $meth .= $fclass;
300     $meth =~ s/Fieldmapper:://;
301     $meth =~ s/::/_/;
302
303     my $obj = $self->editor->$meth( { $ffield => $context->$lfield() } );
304
305     if (@$path) {
306
307         my $obj_list = [];
308         if (!$multi) {
309             $obj_list = [$obj] if ($obj);
310         } else {
311             $obj_list = $obj;
312         }
313
314         $self->_object_by_path( $_, $collector, $label, $path ) for (@$obj_list);
315
316         $obj = $$obj_list[0] if (!$multi);
317         $context->$step( $obj ) if ($obj && !$label);
318
319     } else {
320
321         if ($collector) {
322             my $obj_list = [$obj] if ($obj && !$multi);
323             $obj_list = $obj if ($multi);
324
325             my @new_obj_list;
326             for my $o ( @$obj_list ) {
327                 push @new_obj_list,
328                     OpenILS::Application::Trigger::ModRunner
329                         ->new( $collector, $o )
330                         ->run
331                         ->final_result
332             }
333
334             if (!$multi) {
335                 $obj = $new_obj_list[0];
336             } else {
337                 $obj = \@new_obj_list;
338             }
339         }
340
341         if ($label) {
342             my $node = $self->environment;
343             my $i = 0; my $max = scalar(@$label) - 1;
344             for (; $i < $max; $i++) {
345                 my $part = $$label[$i];
346                 $$node{$part} ||= {};
347                 $node = $$node{$part};
348             }
349             $$node{$$label[-1]} = $obj;
350         } else {
351             $context->$step( $obj ) if ($obj);
352         }
353     }
354
355     return $obj;
356 }
357
358 1;