1 package OpenILS::Application::Trigger::Event;
2 use strict; use warnings;
3 use OpenSRF::EX qw/:try/;
4 use OpenSRF::Utils::JSON;
6 use OpenSRF::Utils::Logger qw/$logger/;
8 use OpenILS::Utils::Fieldmapper;
9 use OpenILS::Utils::CStoreEditor q/:funcs/;
10 use OpenILS::Application::Trigger::ModRunner;
14 my $log = 'OpenSRF::Utils::Logger';
20 $class = ref($class) || $class;
22 return $id if (ref($id) && ref($id) eq $class);
24 my $standalone = $editor ? 0 : 1;
25 $editor ||= new_editor();
27 my $self = bless { id => $id, editor => $editor, standalone => $standalone } => $class;
36 return $self if ($self->event);
39 $self->environment( {} );
42 $log->error("No Event ID provided");
43 die "No Event ID provided";
46 return $self if (!$self->id);
49 $self->editor->retrieve_action_trigger_event([
53 atev => [ qw/event_def/ ],
54 atevdef => [ qw/hook env params/ ]
60 $self->user_data(OpenSRF::Utils::JSON->JSON2perl( $self->event->user_data ))
61 if (defined( $self->event->user_data ));
63 if ($self->event->state eq 'valid') {
65 } elsif ($self->event->state eq 'invalid') {
67 } elsif ($self->event->state eq 'reacting') {
69 } elsif ($self->event->state eq 'reacted') {
72 } elsif ($self->event->state eq 'cleaning') {
75 } elsif ($self->event->state eq 'complete') {
79 } elsif ($self->event->state eq 'error') {
86 $self->update_state('found') || die 'Unable to update event state';
88 my $class = $self->_fm_class_by_hint( $self->event->event_def->hook->core_type );
90 my $meth = "retrieve_" . $class;
91 $meth =~ s/Fieldmapper:://;
94 $self->target( $self->editor->$meth( $self->event->target ) );
101 my $env = shift || $self->environment;
103 return $self if (defined $self->cleanedup);
105 if (defined $self->reacted) {
106 $self->update_state( 'cleaning') || die 'Unable to update event state';
108 my $cleanup = $self->reacted ? $self->event->event_def->cleanup_success : $self->event->event_def->cleanup_failure;
111 OpenILS::Application::Trigger::ModRunner::Cleanup
112 ->new( $cleanup, $env)
120 $log->error("Event cleanup failed with ". shift() );
121 $self->update_state( 'error' ) || die 'Unable to update event state';
124 if ($self->cleanedup) {
125 $self->update_state( 'complete' ) || die 'Unable to update event state';
127 $self->update_state( 'error' ) || die 'Unable to update event state';
131 $self->{cleanedup} = undef;
138 my $env = shift || $self->environment;
140 return $self if (defined $self->reacted);
143 if ($self->event->event_def->group_field) { # can't react individually to a grouped definition
144 $self->{reacted} = undef;
146 $self->update_state( 'reacting') || die 'Unable to update event state';
149 OpenILS::Application::Trigger::ModRunner::Reactor
150 ->new( $self->event->event_def->reactor, $env )
155 $log->error("Event reacting failed with ". shift() );
156 $self->update_state( 'error' ) || die 'Unable to update event state';
159 if (defined $self->reacted) {
160 $self->update_state( 'reacted' ) || die 'Unable to update event state';
162 $self->update_state( 'error' ) || die 'Unable to update event state';
166 $self->{reacted} = undef;
174 return $self if (defined $self->valid);
176 if ($self->build_environment->environment->{complete}) {
177 $self->update_state( 'validating') || die 'Unable to update event state';
180 OpenILS::Application::Trigger::ModRunner::Validator
181 ->new( $self->event->event_def->validator, $self->environment )
186 $log->error("Event validation failed with ". shift() );
187 $self->update_state( 'error' ) || die 'Unable to update event state';
190 if (defined $self->valid) {
192 $self->update_state( 'valid' ) || die 'Unable to update event state';
194 $self->update_state( 'invalid' ) || die 'Unable to update event state';
197 $self->update_state( 'error' ) || die 'Unable to update event state';
200 $self->{valid} = undef
208 return undef unless (ref $self);
211 $self->{cleanedup} = $c if (defined $c);
212 return $self->{cleanedup};
217 return undef unless (ref $self);
220 $self->{user_data} = $r if (defined $r);
221 return $self->{user_data};
226 return undef unless (ref $self);
229 $self->{reacted} = $r if (defined $r);
230 return $self->{reacted};
235 return undef unless (ref $self);
238 $self->{valid} = $v if (defined $v);
239 return $self->{valid};
244 return undef unless (ref $self);
247 $self->{event} = $e if (defined $e);
248 return $self->{event};
253 return undef unless (ref $self);
256 $self->{id} = $i if (defined $i);
262 return undef unless (ref $self);
265 $self->{environment} = $e if (defined $e);
266 return $self->{environment};
271 return undef unless (ref $self);
274 $self->{editor} = $e if (defined $e);
275 return $self->{editor};
280 return undef unless (ref $self);
282 die 'Cannot unfind a reacted event' if (defined $self->reacted);
284 $self->update_state( 'pending' ) || die 'Unable to update event state';
286 $self->{event} = undef;
287 $self->{environment} = undef;
293 return undef unless (ref $self);
296 $self->{target} = $t if (defined $t);
297 return $self->{target};
302 return undef unless (ref $self);
305 $self->{standalone} = $t if (defined $t);
306 return $self->{standalone};
311 return undef unless ($self && ref $self);
314 return undef unless ($state);
318 if ($self->standalone) {
319 $self->editor->xact_begin || return undef;
322 my $e = $self->editor->retrieve_action_trigger_event( $self->id );
324 $log->error( "Could not retrieve object ".$self->id." for update" ) if (!$e);
328 if ($fields && ref($fields)) {
329 $e->$_($$fields{$_}) for (keys %$fields);
332 $log->info( "Retrieved object ".$self->id." for update" );
333 $e->start_time( 'now' ) unless $e->start_time;
334 $e->update_time( 'now' );
335 $e->update_process( $$ );
338 $e->clear_start_time() if ($e->state eq 'pending');
340 my $ok = $self->editor->update_action_trigger_event( $e );
342 $self->editor->xact_rollback if ($self->standalone);
343 $log->error( "Update of event ".$self->id." failed" );
346 $e = $self->editor->data;
347 $e = $self->editor->retrieve_action_trigger_event( $e ) if (!ref($e));
349 $log->error( "Update of event ".$self->id." did not return an object" );
352 $log->info( "Update of event ".$e->id." suceeded" );
353 $ok = $self->editor->xact_commit if ($self->standalone);
357 $self->event->start_time( $e->start_time );
358 $self->event->update_time( $e->update_time );
359 $self->event->update_process( $e->update_process );
360 $self->event->state( $e->state );
366 my $current_environment;
368 sub build_environment {
370 return $self if ($self->environment->{complete});
372 $self->update_state( 'collecting') || die 'Unable to update event state';
376 my $compartment = new Safe;
377 $compartment->permit(':default','require','dofile','caller');
378 $compartment->share('$current_environment');
380 $self->environment->{EventProcessor} = $self;
381 $self->environment->{target} = $self->target;
382 $self->environment->{event} = $self->event;
383 $self->environment->{template} = $self->event->event_def->template;
384 $self->environment->{user_data} = $self->user_data;
386 $current_environment = $self->environment;
388 $self->environment->{params}{ $_->param } = $compartment->reval($_->value) for ( @{$self->event->event_def->params} );
390 for my $e ( @{$self->event->event_def->env} ) {
392 @path = split(/\./, $e->path) if ($e->path);
393 @label = split(/\./, $e->label) if ($e->label);
395 $self->_object_by_path( $self->target, $e->collector, \@label, \@path );
398 if ($self->event->event_def->group_field) {
399 my @group_path = split(/\./, $self->event->event_def->group_field);
400 my $group_object = $self->_object_by_path( $self->target, undef, [], \@group_path );
403 $self->environment->{complete} = 1;
405 $log->error( shift() );
406 $self->update_state( 'error' ) || die 'Unable to update event state';
409 if ($self->environment->{complete}) {
410 $self->update_state( 'collected' ) || die 'Unable to update event state';
412 $self->update_state( 'error' ) || die 'Unable to update event state';
418 sub _fm_class_by_hint {
423 Fieldmapper->publish_fieldmapper->{$_}->{hint} eq $hint
424 } keys %{ Fieldmapper->publish_fieldmapper };
429 sub _object_by_path {
432 my $collector = shift;
436 my $step = shift(@$path);
438 my $fhint = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{class};
439 my $fclass = $self->_fm_class_by_hint( $fhint );
441 my $ffield = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{key};
442 my $rtype = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{reltype};
444 my $meth = 'retrieve_';
447 if ($rtype ne 'has_a') {
450 $lfield = $context->Identity;
454 $meth =~ s/Fieldmapper:://;
457 my $ed = grep( /open-ils.cstore/, @{$fclass->Controller} ) ?
461 my $obj = $context->$step();
466 { $ffield => $context->$lfield() } :
475 $obj_list = [$obj] if ($obj);
481 my @path_clone = @$path;
482 $self->_object_by_path( $_, $collector, $label, \@path_clone );
485 $obj = $$obj_list[0] if (!$multi || $rtype eq 'might_have');
486 $context->$step( $obj ) if ($obj && (!$label || !@$label));
491 my $obj_list = [$obj] if ($obj && !$multi);
492 $obj_list = $obj if ($multi);
495 for my $o ( @$obj_list ) {
497 OpenILS::Application::Trigger::ModRunner::Collector
498 ->new( $collector, $o )
504 $obj = $new_obj_list[0];
506 $obj = \@new_obj_list;
510 if ($label && @$label) {
511 my $node = $self->environment;
512 my $i = 0; my $max = scalar(@$label);
513 for (; $i < $max; $i++) {
514 my $part = $$label[$i];
515 $$node{$part} ||= {};
516 $node = $$node{$part};
518 $$node{$$label[-1]} = $obj;
520 $obj = $$obj[0] if $rtype eq 'might_have';
521 $context->$step( $obj ) if ($obj);