]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/EventGroup.pm
Merge branch 'master' of git.evergreen-ils.org:Evergreen-DocBook into doc_consolidati...
[Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / Application / Trigger / EventGroup.pm
1 package OpenILS::Application::Trigger::EventGroup;
2 use strict; use warnings;
3 use OpenILS::Application::Trigger::Event;
4 use base 'OpenILS::Application::Trigger::Event';
5 use OpenSRF::EX qw/:try/;
6
7 use OpenSRF::Utils::Logger qw/$logger/;
8
9 use OpenILS::Utils::Fieldmapper;
10 use OpenILS::Utils::CStoreEditor q/:funcs/;
11 use OpenILS::Application::Trigger::ModRunner;
12
13 my $log = 'OpenSRF::Utils::Logger';
14
15 sub new_impl {
16     my $class = shift;
17     my @ids = @{shift()};
18     my $nochanges = shift;
19
20     $class = ref($class) || $class;
21
22     my $editor = new_editor(xact=>1);
23
24     my $self = bless {
25         environment => {},
26         events      => [
27             map {
28                 ref($_) ?
29                     do { $_->standalone(0); $_->editor($editor); $_ } :
30                     OpenILS::Application::Trigger::Event->new($_, $editor, $nochanges)
31             } @ids
32         ],
33         ids         => [ map { ref($_) ? $_->id : $_ } @ids ],
34         editor      => $editor
35     } => $class;
36
37
38     $self->editor->xact_commit; # flush out those updates
39     $self->editor->xact_begin;
40
41     return $self;
42 }
43
44 sub new_nochanges {
45     my $class = shift;
46     my @ids = @_;
47
48     return new_impl($class, \@ids, 1);
49 }
50
51 sub new {
52     my $class = shift;
53     my @ids = @_;
54
55     return new_impl($class, \@ids);
56 }
57
58 sub react {
59     my $self = shift;
60
61     return $self if (defined $self->reacted);
62
63     if ($self->valid) {
64         $self->update_state( 'reacting') || die 'Unable to update event group state';
65         $self->build_environment;
66
67         try {
68             $self->reacted(
69                 OpenILS::Application::Trigger::ModRunner::Reactor
70                     ->new( $self->event->event_def->reactor, $self->environment )
71                     ->run
72                     ->final_result
73             );
74         } otherwise {
75             $log->error("Event reacting failed with ". shift() );
76             $self->update_state( 'error' ) || die 'Unable to update event group state';
77         };
78
79         if (defined $self->reacted) {
80             $self->update_state( 'reacted' ) || die 'Unable to update event group state';
81         } else {
82             $self->update_state( 'error' ) || die 'Unable to update event group state';
83         }
84     } else {
85         $self->{reacted} = undef;
86     }
87     return $self;
88 }
89
90 sub validate {
91     my $self = shift;
92
93     return $self if (defined $self->valid);
94
95     $self->update_state( 'validating') || die 'Unable to update event group state';
96     $self->editor->xact_begin;
97
98     my @valid_events;
99     try {
100         for my $event ( @{ $self->events } ) {
101             $event->validate;
102             push @valid_events, $event if ($event->valid);
103         }
104         $self->valid(1) if (@valid_events);
105         $self->{events} = \@valid_events;
106         $self->{ids} = [ map { $_->id } @valid_events ];
107         $self->editor->xact_commit;
108     } otherwise {
109         $log->error("Event group validation failed with ". shift() );
110         $self->editor->xact_rollback;
111         $self->update_state( 'error' ) || die 'Unable to update event group state';
112     };
113
114     return $self;
115 }
116  
117 sub revalidate_test {
118     my $self = shift;
119
120     $self->editor->xact_begin;
121
122     my @valid_events;
123     try {
124         for my $event ( @{ $self->events } ) {
125             push @valid_events, $event->id if $event->revalidate_test;
126         }
127         $self->editor->xact_rollback;
128     } otherwise {
129         $log->error("Event group validation failed with ". shift());
130         $self->editor->xact_rollback;
131     };
132
133     return \@valid_events;
134 }
135  
136 sub cleanedup {
137     my $self = shift;
138     return undef unless (ref $self);
139
140     my $c = shift;
141     $self->{cleanedup} = $c if (defined $c);
142     return $self->{cleanedup};
143 }
144
145 sub reacted {
146     my $self = shift;
147     return undef unless (ref $self);
148
149     my $r = shift;
150     $self->{reacted} = $r if (defined $r);
151     return $self->{reacted};
152 }
153
154 sub valid {
155     my $self = shift;
156     return undef unless (ref $self);
157
158     my $v = shift;
159     $self->{valid} = $v if (defined $v);
160     return $self->{valid};
161 }
162
163 sub event {
164     my $self = shift;
165     return undef unless (ref $self);
166
167     return $self->{events}[0]->event;
168 }
169
170 sub events {
171     my $self = shift;
172     return undef unless (ref $self);
173
174     return $self->{events};
175 }
176
177 sub ids {
178     my $self = shift;
179     return undef unless (ref $self);
180
181     return $self->{ids};
182 }
183
184 sub environment {
185     my $self = shift;
186     return undef unless (ref $self);
187
188     my $e = shift;
189     $self->{environment} = $e if (defined $e);
190     return $self->{environment};
191 }
192
193 sub editor {
194     my $self = shift;
195     return undef unless (ref $self);
196
197     my $e = shift;
198     $self->{editor} = $e if (defined $e);
199     return $self->{editor};
200 }
201
202 sub unfind {
203     my $self = shift;
204     return undef unless (ref $self);
205
206     die 'Cannot unfind a reacted event group' if (defined $self->reacted);
207
208     $self->update_state( 'pending' ) || die 'Unable to update event group state';
209     $self->{events} = undef;
210     return $self;
211 }
212
213 sub update_state {
214     my $self = shift;
215     return undef unless ($self && ref $self);
216
217     my $state = shift;
218     return undef unless ($state);
219
220     my $fields = shift;
221
222     $self->editor->xact_begin || return undef;
223
224     my @oks;
225     my $ok;
226     my $last_updated;
227     for my $event ( @{ $self->events } ) {
228         my $e = $self->editor->retrieve_action_trigger_event( $event->id );
229         $e->start_time( 'now' ) unless $e->start_time;
230         $e->update_time( 'now' );
231         $e->update_process( $$ );
232         $e->state( $state );
233
234         $e->clear_start_time() if ($e->state eq 'pending');
235
236         if ($fields && ref($fields)) {
237             $e->$_($$fields{$_}) for (keys %$fields);
238         }
239
240         my $ok = $self->editor->update_action_trigger_event( $e );
241         if ($ok) {
242             push @oks, $ok;
243             $last_updated = $e->id;
244         }
245     }
246
247     if (scalar(@oks) < scalar(@{ $self->ids })) {
248         $self->editor->xact_rollback;
249         return undef;
250     } 
251
252     my $updated = $self->editor->retrieve_action_trigger_event($last_updated);
253     $ok = $self->editor->xact_commit;
254
255     if ($ok) {
256         for my $event ( @{ $self->events } ) {
257             my $e = $event->event;
258             $e->start_time( $updated->start_time );
259             $e->update_time( $updated->update_time );
260             $e->update_process( $updated->update_process );
261             $e->state( $updated->state );
262         }
263     }
264
265     return $ok || undef;
266 }
267
268 sub findEvent {
269     my $self = shift;
270     my $member = shift;
271
272     $member = $member->id if (ref($member));
273
274     my @list = grep { $member == $_->id } @{ $self->events };
275
276     return shift(@list);
277 }
278
279 sub build_environment {
280     my $self = shift;
281     my $env = $self->environment;
282
283     $$env{EventProcessor} = $self;
284     $$env{target} = [];
285     $$env{event} = [];
286     $$env{user_data} = [];
287     for my $e ( @{ $self->events } ) {
288         for my $env_part ( keys %{ $e->environment } ) {
289             next if ($env_part eq 'EventProcessor');
290             if ($env_part eq 'target') {
291                 push @{ $$env{target} }, $e->environment->{target};
292             } elsif ($env_part eq 'event') {
293                 push @{ $$env{event} }, $e->environment->{event};
294             } elsif ($env_part eq 'user_data') {
295                 push @{ $$env{user_data} }, $e->environment->{user_data};
296             } else {
297                 $$env{$env_part} = $e->environment->{$env_part};
298             }
299         }
300     }
301
302     return $self;
303 }
304
305 1;