1 package OpenILS::Application::Trigger::Event;
2 use strict; use warnings;
3 use OpenSRF::EX qw/:try/;
5 use OpenSRF::Utils::Logger qw/:logger/;
7 use OpenILS::Utils::Fieldmapper;
8 use OpenILS::Utils::CStoreEditor q/:funcs/;
9 use OpenILS::Application::Trigger::ModRunner;
11 my $log = 'OpenSRF::Utils::Logger';
17 $class = ref($class) || $class;
19 return $id if (ref($id) && ref($id) == $class);
21 my $standalone = $editor ? 0 : 1;
22 $editor ||= new_editor();
24 my $self = bless { id => $id, editor => $editor, standalone => $standalone } => $class;
33 return $self if ($self->event);
36 $self->environment( {} );
39 $log->error("No Event ID provided");
40 die "No Event ID provided";
43 return $self if (!$self->id);
46 $self->editor->retrieve_action_trigger_event([
50 atev => [ qw/event_def/ ],
51 atevdef => [ qw/hook env params/ ]
57 if ($self->event->state eq 'valid') {
59 } elsif ($self->event->state eq 'invalid') {
61 } elsif ($self->event->state eq 'reacting') {
63 } elsif ($self->event->state eq 'reacted') {
66 } elsif ($self->event->state eq 'cleaning') {
69 } elsif ($self->event->state eq 'complete') {
73 } elsif ($self->event->state eq 'error') {
80 $self->update_state('found') || die 'Unable to update event state';
82 my $class = $self->_fm_class_by_hint( $self->event->event_def->hook->core_type );
84 my $meth = "retrieve_" . $class;
85 $meth =~ s/Fieldmapper:://;
88 $self->target( $self->editor->$meth( $self->event->target ) );
95 my $env = shift || $self->environment;
97 return $self if (defined $self->cleanedup);
99 if (defined $self->reacted) {
100 $self->update_state( 'cleaning') || die 'Unable to update event state';
102 my $cleanup = $self->reacted ? $self->event->event_def->cleanup_success : $self->event->event_def->cleanup_failure;
105 OpenILS::Application::Trigger::ModRunner::Cleanup
106 ->new( $cleanup, $env)
114 $log->error( shift() );
115 $self->update_state( 'error' ) || die 'Unable to update event state';
118 if ($self->cleanedup) {
119 $self->update_state( 'complete' ) || die 'Unable to update event state';
121 $self->update_state( 'error' ) || die 'Unable to update event state';
125 $self->{cleanedup} = undef;
132 my $env = shift || $self->environment;
134 return $self if (defined $self->reacted);
137 if ($self->event->event_def->group_field) { # can't react individually to a grouped definition
138 $self->{reacted} = undef;
140 $self->update_state( 'reacting') || die 'Unable to update event state';
143 OpenILS::Application::Trigger::ModRunner::Reactor
144 ->new( $self->event->event_def->reactor, $env )
149 $log->error( shift() );
150 $self->update_state( 'error' ) || die 'Unable to update event state';
153 if (defined $self->reacted) {
154 $self->update_state( 'reacted' ) || die 'Unable to update event state';
156 $self->update_state( 'error' ) || die 'Unable to update event state';
160 $self->{reacted} = undef;
168 return $self if (defined $self->valid);
170 if ($self->build_environment->environment->{complete}) {
171 $self->update_state( 'validating') || die 'Unable to update event state';
174 OpenILS::Application::Trigger::ModRunner::Validator
175 ->new( $self->event->event_def->validator, $self->environment )
180 $log->error( shift() );
181 $self->update_state( 'error' ) || die 'Unable to update event state';
184 if (defined $self->valid) {
186 $self->update_state( 'valid' ) || die 'Unable to update event state';
188 $self->update_state( 'invalid' ) || die 'Unable to update event state';
191 $self->update_state( 'error' ) || die 'Unable to update event state';
194 $self->{valid} = undef
202 return undef unless (ref $self);
205 $self->{cleanedup} = $c if (defined $c);
206 return $self->{cleanedup};
211 return undef unless (ref $self);
214 $self->{reacted} = $r if (defined $r);
215 return $self->{reacted};
220 return undef unless (ref $self);
223 $self->{valid} = $v if (defined $v);
224 return $self->{valid};
229 return undef unless (ref $self);
232 $self->{event} = $e if (defined $e);
233 return $self->{event};
238 return undef unless (ref $self);
241 $self->{id} = $i if (defined $i);
247 return undef unless (ref $self);
250 $self->{environment} = $e if (defined $e);
251 return $self->{environment};
256 return undef unless (ref $self);
259 $self->{editor} = $e if (defined $e);
260 return $self->{editor};
265 return undef unless (ref $self);
267 die 'Cannot unfind a reacted event' if (defined $self->reacted);
269 $self->update_state( 'pending' ) || die 'Unable to update event state';
271 $self->{event} = undef;
272 $self->{environment} = undef;
278 return undef unless (ref $self);
281 $self->{target} = $t if (defined $t);
282 return $self->{target};
287 return undef unless (ref $self);
290 $self->{standalone} = $t if (defined $t);
291 return $self->{standalone};
296 return undef unless ($self && ref $self);
299 return undef unless ($state);
303 if ($self->standalone) {
304 $self->editor->xact_begin || return undef;
307 my $e = $self->editor->retrieve_action_trigger_event( $self->id );
309 $log->error( "Could not retrieve object ".$self->id." for update" ) if (!$e);
313 if ($fields && ref($fields)) {
314 $e->$_($$fields{$_}) for (keys %$fields);
317 $log->info( "Retrieved object ".$self->id." for update" );
318 $e->start_time( 'now' ) unless $e->start_time;
319 $e->update_time( 'now' );
320 $e->update_process( $$ );
323 $e->clear_start_time() if ($e->state eq 'pending');
325 my $ok = $self->editor->update_action_trigger_event( $e );
327 $self->editor->xact_rollback if ($self->standalone);
328 $log->error( "Update of event ".$self->id." failed" );
331 $e = $self->editor->data;
332 $e = $self->editor->retrieve_action_trigger_event( $e ) if (!ref($e));
334 $log->error( "Update of event ".$self->id." did not return an object" );
337 $log->info( "Update of event ".$e->id." suceeded" );
338 $ok = $self->editor->xact_commit if ($self->standalone);
342 $self->event->start_time( $e->start_time );
343 $self->event->update_time( $e->update_time );
344 $self->event->update_process( $e->update_process );
345 $self->event->state( $e->state );
351 sub build_environment {
353 return $self if ($self->environment->{complete});
355 $self->update_state( 'collecting') || die 'Unable to update event state';
359 $self->environment->{target} = $self->target;
360 $self->environment->{event} = $self->event;
361 $self->environment->{template} = $self->event->event_def->template;
363 $self->environment->{params}{ $_->param } = eval $_->value for ( @{$self->event->event_def->params} );
365 for my $e ( @{$self->event->event_def->env} ) {
367 @path = split(/\./, $e->path) if ($e->path);
368 @label = split(/\./, $e->label) if ($e->label);
370 $self->_object_by_path( $self->target, $e->collector, \@label, \@path );
373 if ($self->event->event_def->group_field) {
374 my @group_path = split(/\./, $self->event->event_def->group_field);
375 my $group_object = $self->_object_by_path( $self->target, undef, [], \@group_path );
378 $self->environment->{complete} = 1;
380 $log->error( shift() );
381 $self->update_state( 'error' ) || die 'Unable to update event state';
384 if ($self->environment->{complete}) {
385 $self->update_state( 'collected' ) || die 'Unable to update event state';
387 $self->update_state( 'error' ) || die 'Unable to update event state';
393 sub _fm_class_by_hint {
398 Fieldmapper->publish_fieldmapper->{$_}->{hint} eq $hint
399 } keys %{ Fieldmapper->publish_fieldmapper };
404 sub _object_by_path {
407 my $collector = shift;
411 my $step = shift(@$path);
413 my $fhint = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{class};
414 my $fclass = $self->_fm_class_by_hint( $fhint );
416 my $ffield = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{key};
417 my $rtype = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{reltype};
419 my $meth = 'retrieve_';
422 if ($rtype ne 'has_a') {
425 $lfield = $context->Identity;
429 $meth =~ s/Fieldmapper:://;
432 my $ed = grep( /open-ils.cstore/, @{$fclass->Controller} ) ?
436 my $obj = $context->$step();
441 { $ffield => $context->$lfield() } :
449 if (!$multi || $rtype eq 'might_have') {
450 $obj_list = [$obj] if ($obj);
455 $self->_object_by_path( $_, $collector, $label, $path ) for (@$obj_list);
457 $obj = $$obj_list[0] if (!$multi || $rtype eq 'might_have');
458 $context->$step( $obj ) if ($obj && (!$label || !@$label));
463 my $obj_list = [$obj] if ($obj && !$multi);
464 $obj_list = $obj if ($multi);
467 for my $o ( @$obj_list ) {
469 OpenILS::Application::Trigger::ModRunner::Collector
470 ->new( $collector, $o )
476 $obj = $new_obj_list[0];
478 $obj = \@new_obj_list;
482 if ($label && @$label) {
483 my $node = $self->environment;
484 my $i = 0; my $max = scalar(@$label);
485 for (; $i < $max; $i++) {
486 my $part = $$label[$i];
487 $$node{$part} ||= {};
488 $node = $$node{$part};
490 $$node{$$label[-1]} = $obj;
492 $context->$step( $obj ) if ($obj);