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