File Coverage

blib/lib/Workflow/Wfmc.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Workflow::Wfmc;
2            
3 1     1   20583 use 5.008003;
  1         4  
  1         39  
4 1     1   6 use strict;
  1         2  
  1         28  
5 1     1   4 use warnings;
  1         5  
  1         26  
6 1     1   940 use Data::Dumper;
  1         9540  
  1         80  
7 1     1   345 use XML::Simple qw(XMLin XMLout);
  0            
  0            
8            
9             require Exporter;
10             use AutoLoader qw(AUTOLOAD);
11            
12             our @ISA = qw(Exporter);
13            
14             # Items to export into callers namespace by default. Note: do not export
15             # names by default without a very good reason. Use EXPORT_OK instead.
16             # Do not simply export all your public functions/methods/constants.
17            
18             # This allows declaration use Workflow::Wfmc ':all';
19             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
20             # will save memory.
21             our %EXPORT_TAGS = ( 'all' => [ qw(
22            
23             ) ] );
24            
25             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
26            
27             our @EXPORT = qw(
28            
29             );
30            
31             our $VERSION = '0.01e';
32            
33             my $PACKAGE = __PACKAGE__;
34             our @LOGOPT;
35             my %LOGFLAG = (
36             'emerg' => 0,
37             'crit' => 0,
38             'error' => 0,
39             'warn' => 0,
40             'notice' => 0,
41             'info' => 0,
42             'debug' => 0,
43             ); # apache logging levels
44             my $INITIALIZED = 0;
45             my $CONFIG;
46             my $MYSELF;
47            
48             # Preloaded methods go here.
49            
50             # Autoload methods go after =cut, and are processed by the autosplit program.
51            
52             sub new {
53             my $invocant = shift;
54             my $class = ref($invocant) || $invocant;
55             my $self = {};
56             if (defined $_[0] && defined $_[1] && shift eq 'Id') {
57             $self->{Id} = shift;
58             $self->{DataFields} = undef; # DataFields are variables used in workflow
59             $self->{FormalParameters} = undef; # FormalParameters are variables used in workflow
60             }
61             else
62             {
63             die "(die): Lack of Id in subroutine new of $PACKAGE"
64             }
65             $MYSELF = $self;
66             bless ($self,$class);
67             return $self;
68             }
69             #sub DESTROY
70             #{
71             # my $invocant = shift;
72             # print STDERR "(debug): Destroying object of $PACKAGE\n";
73             # print STDERR "(debug): Argh. Life was sweet.\n";
74             #}
75            
76             sub Id
77             {
78             my $invocant = shift;
79             $invocant->logger->debug("Entering subroutine Id of $PACKAGE");
80             $invocant->logger->debug("Leaving subroutine Id of $PACKAGE");
81             (@_) ? return shift : return $invocant->{Id};
82             }
83            
84             sub workflow {
85             my $invocant = shift;
86             my ($wfps,$wfp_id) = (shift,shift);
87             my $wfp = $wfps->{'WorkflowProcess'}->[$wfp_id-1];
88             my $wfp_pheader = $wfp->{'ProcessHeader'};
89             my $wfp_fparam = $wfp->{'FormalParameters'};
90             my $wfp_dataf = $wfp->{'DataFields'};
91             my $wfp_part = $wfp->{'Partitions'};
92             my $wfp_app = $wfp->{'Applications'};
93             my $wfp_act = $wfp->{'Activities'};
94             my $wfp_trans = $wfp->{'Transitions'};
95             #print Dumper($wfp_trans);
96             return $invocant;
97             }
98            
99             sub debug
100             {
101             my $invocant = shift;
102             return $invocant unless($LOGFLAG{'debug'});
103             if(@_)
104             {
105             my @lines = split("\n",shift);
106             my $n = 0;
107             my $length = $#lines + 1;
108             foreach my $line (@lines)
109             {
110             $n++;
111             print STDERR "(debug)\t($n/$length):\t$line\n" ;
112             }
113             }
114             else
115             {
116             print STDERR "(debug)\t(1/1):\tLack of content in subroutine debug of $PACKAGE";
117             }
118             return $invocant;
119             }
120             ;
121             sub warn
122             {
123             my $invocant = shift;
124             return $invocant unless($LOGFLAG{'warn'});
125             if(@_)
126             {
127             my @lines = split("\n",shift);
128             my $n = 0;
129             my $length = $#lines + 1;
130             foreach my $line (@lines)
131             {
132             $n++;
133             print STDERR "(warn)\t($n/$length):\t$line\n" ;
134             }
135             }
136             else
137             {
138             print STDERR "(warn)\t(1/1):\tLack of content in subroutine warn of $PACKAGE";
139             }
140             return $invocant;
141             }
142             ;
143             sub error
144             {
145             my $invocant = shift;
146             #return $invocant unless($LOGFLAG{'error'});
147             if(@_)
148             {
149             my @lines = split("\n",shift);
150             my $n = 0;
151             my $length = $#lines + 1;
152             foreach my $line (@lines)
153             {
154             $n++;
155             print STDERR "(error)\t($n/$length):\t$line\n" ;
156             }
157             if(my $vie = $invocant->error_notify_via)
158             {
159             if ($vie =~ /\bemail\b/)
160             {
161             my $body = join('',@lines);
162             my $subject = 'STM error message';
163             $invocant->sendmail($subject,$body);
164             }
165             if ($vie =~ /\bjabber\b/)
166             {
167             my $body = join('',@lines);
168             my $subject = 'STM error message';
169             $invocant->sendjabber($subject,$body);
170             }
171             }
172            
173             }
174             else
175             {
176             print STDERR "(error)\t(1/1):\tLack of content in subroutine error of $PACKAGE";
177             }
178             return $invocant;
179             }
180             ;
181            
182             sub info
183             {
184             my $invocant = shift;
185             return $invocant unless($LOGFLAG{'info'});
186             if(@_)
187             {
188             my @lines = split("\n",shift);
189             my $n = 0;
190             my $length = $#lines + 1;
191             foreach my $line (@lines)
192             {
193             $n++;
194             print STDERR "(info)\t($n/$length):\t$line\n" ;
195             }
196             }
197             else
198             {
199             print STDERR "(info)\t(1/1):\tLack of content in subroutine info of $PACKAGE";
200             }
201             return $invocant;
202             }
203             sub notice
204             {
205             my $invocant = shift;
206             return $invocant unless($LOGFLAG{'notice'});
207             if(@_)
208             {
209             my @lines = split("\n",shift);
210             my $n = 0;
211             my $length = $#lines + 1;
212             foreach my $line (@lines)
213             {
214             $n++;
215             print STDERR "(notice)\t($n/$length):\t$line\n" ;
216             }
217             }
218             else
219             {
220             print STDERR "(notice)\t(1/1):\tLack of content in subroutine notice of $PACKAGE";
221             }
222             return $invocant;
223             }
224             sub emerg
225             {
226             my $invocant = shift;
227             return $invocant unless($LOGFLAG{'emerg'});
228             if(@_)
229             {
230             my @lines = split("\n",shift);
231             my $n = 0;
232             my $length = $#lines + 1;
233             foreach my $line (@lines)
234             {
235             $n++;
236             print STDERR "(emerg)\t($n/$length):\t$line\n" ;
237             }
238             }
239             else
240             {
241             print STDERR "(emerg)\t(1/1):\tLack of content in subroutine emerg of $PACKAGE";
242             }
243             return $invocant;
244             }
245             sub crit
246             {
247             my $invocant = shift;
248             return $invocant unless($LOGFLAG{'crit'});
249             if(@_)
250             {
251             my @lines = split("\n",shift);
252             my $n = 0;
253             my $length = $#lines + 1;
254             foreach my $line (@lines)
255             {
256             $n++;
257             print STDERR "(crit)\t($n/$length):\t$line\n" ;
258             }
259             }
260             else
261             {
262             print STDERR "(crit)\t(1/1):\tLack of content in subroutine crit of $PACKAGE";
263             }
264             return $invocant;
265             }
266            
267             sub logger # also a initializer ;-)
268             {
269             my $invocant = shift;
270             unless($INITIALIZED)
271             {
272             foreach my $n (@LOGOPT)
273             {
274             $LOGFLAG{$n} = 1;
275             }
276             $INITIALIZED = 1;
277             }
278             return $invocant;
279             }
280            
281            
282             sub load_conf
283             {
284             use XML::XPath;
285             my $invocant = shift;
286             $invocant->logger->debug("Entering subroutine load_conf of $PACKAGE");
287             my ($file,$nodeset);
288             if(@_)
289             {
290             $file = shift;
291             die "(die): Configuration file $file does not exit or empty of $PACKAGE" unless( -s $file);
292             $invocant->logger->debug("Config file name $file passed");
293             $CONFIG = XML::XPath->new(filename => $file );
294             $invocant->logger->debug("XML::XPath object created");
295             $nodeset = $CONFIG->find('/'); # find all paragraphs
296             $invocant->logger->debug("Finding config root node");
297             foreach my $node ($nodeset->get_nodelist)
298             {
299             $invocant->logger->debug(XML::XPath::XMLParser::as_string($node));
300             }
301             $invocant->logger->debug("Config file $file loaded");
302             }
303             else
304             {
305             die "(die): Lack of copnfiguration file name in subroutine load_conf of $PACKAGE";
306             }
307             $invocant->logger->debug("Leaving subroutine load_conf of $PACKAGE");
308             return $CONFIG;
309             }
310            
311             sub init_data_fields # intialize DataFields (with values if possible) using the workflow configuration file
312             {
313             my ($invocant,$wfp_id) = (shift,shift);
314             $invocant->logger->debug("Entering subroutine init_data_fields of $PACKAGE");
315             my $xml = $invocant->get_wfp_element($wfp_id,'DataFields');
316             my $perl = XMLin($xml);
317             my $df = $perl->{'DataField'};
318             my @df;
319             my $datafields;
320             eval{@df = @$df;};
321             push @df, $df if($@);
322             foreach(@df){
323             if(defined $_->{'InitialValue'}){
324             $invocant->{DataFields}->{$_->{'Id'}} = $_->{'InitialValue'};
325             }else{
326             $invocant->{DataFields}->{$_->{'Id'}} = '';
327             }
328             }
329             $invocant->logger->debug("Leaving subroutine init_data_fields of $PACKAGE");
330             return $invocant->{DataFields};
331             }
332            
333             sub data_fields # set elements in DataFields and retrun a pointer to the DataFields
334             {
335             my ($invocant,$df) = (shift,shift);
336             $invocant->logger->debug("Entering subroutine data_fields of $PACKAGE");
337             if(defined $df){
338             my %df = %$df;
339             my @chiave = keys(%df);
340             foreach(@chiave){
341             $invocant->{DataFields}->{$_} = $df->{$_};
342             }
343             }
344             $invocant->logger->debug("Leaving subroutine data_fields of $PACKAGE");
345             return $invocant->{DataFields};
346             }
347            
348            
349             # This method generates PERL code to call some library (PERL class). Produces something like
350             # use Kai::Order::Simple;
351             # Kai::Order::Simple::checkData('orderInfo'=>'Blah',);
352             sub get_perl_by_method{ # only accept strings as import data
353             my ($invocant,$cls,$mtd,$param) = @_;
354             #print $_,"\n" foreach(@param);exit;
355             $invocant->logger->debug("Entering subroutine parser of $PACKAGE");
356             my $perl = "use $cls\;\n";
357             if(defined $mtd){
358             $perl .= $cls.'::';
359             $perl .= $mtd.'({';
360             }
361             foreach(@$param){
362             $perl .= $_;
363             $perl .= q{,};
364             }
365             $perl .= "})\;\n";
366             $invocant->logger->debug("Leaving subroutine get_perl_by_method of $PACKAGE");
367             $perl;
368             }
369            
370            
371             sub get_activity_by_id{ # Return the Activity (identified by activity ID) subnode of the workflow configuration file
372             my ($invocant,$wfp_id,$act_id) = @_;
373             $invocant->logger->debug("Entering subroutine get_activity_by_id of $PACKAGE");
374             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/Activities/Activity[@Id='|.$act_id.q|']|); # find all paragraphs
375             foreach my $node ($nodeset->get_nodelist)
376             {
377             $invocant->logger->debug("Leaving subroutine get_activity_by_id of $PACKAGE");
378             return XML::XPath::XMLParser::as_string($node);
379             }
380             }
381            
382             sub get_dest_act_id{ # Return the Transaction (identified by 'From') subnodes of the workflow configuration file
383             my ($invocant,$wfp_id,$act_id) = @_;
384             $invocant->logger->debug("Entering subroutine get_activity_by_id of $PACKAGE");
385             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/Transitions/Transition[@From='|.$act_id.q|']|); # find all paragraphs
386             my @res;
387             foreach my $node ($nodeset->get_nodelist)
388             {
389             push @res, XML::XPath::XMLParser::as_string($node);
390             }
391             $invocant->logger->debug("Leaving subroutine get_activity_by_id of $PACKAGE");
392             \@res;
393             }
394            
395             sub get_perl_by_act_id{ # Return PERL code to call for a given Activity ID
396             use XML::Simple qw|XMLin XMLout|;
397             my ($invocant,$order_class,$wfp_id,$init_act_id) = @_;
398             $invocant->logger->debug("Entering subroutine get_activity_by_id of $PACKAGE");
399             my $act_xml = $invocant->get_activity_by_id($wfp_id,$init_act_id);
400             my $act_perl = XMLin($act_xml);
401             my $method = $act_perl->{'Implementation'}->{'Tool'}->{'Id'};
402             my $params = $act_perl->{'Implementation'}->{'Tool'}->{'ActualParameters'}->{'ActualParameter'};
403             my (@p,@params);
404             eval{@p = @$params;};
405             my $p;
406             if($@){
407             if (defined $params){
408             $invocant->{DataFields}->{$params} =~ s/'/\\'/g ;
409             $p =qq|'$params'=>'$invocant->{DataFields}->{$params}'|;
410             push @params,$p;
411             }
412             }else{
413             foreach(@p){
414             $invocant->{DataFields}->{$_} =~ s/'/\\'/g;
415             my $p = qq|'$_'=>'$invocant->{DataFields}->{$_}'|;
416             push @params,$p;
417             }
418             }
419             my $perl = $invocant->get_perl_by_method($order_class,$method,\@params); # get the perl code
420             $invocant->logger->debug("Leaving subroutine get_perl_by_act_id of $PACKAGE");
421             $perl;
422             }
423            
424            
425             sub get_conditions # Produces a hash from the Transaction (identified by 'From') subnodes of the workflow configuration file
426             {
427             my ($invocant,$wfp_id,$init_act_id) = @_;
428             $invocant->logger->debug("Entering subroutine get_conditions of $PACKAGE");
429             my $dest_act_id = $invocant->get_dest_act_id($wfp_id,$init_act_id); # get the XML leafs specifying 'From' ID
430             my @cond_hash;
431             my @operators = ('==','!=');
432             foreach (@$dest_act_id)
433             {
434             my $perl = XMLin($_);
435             my $dest = $perl->{'To'};
436             my $cond = $perl->{'Condition'};
437             if(ref $cond){ # OTHERWISE, EXCEPTION
438             push @cond_hash, {
439             'param' => '',
440             'value' => '',
441             'dest' => $dest,
442             'op' => $cond->{'Type'}, # OTHERWISE, EXCEPTION
443             };
444             }elsif($cond){ # var==, var!=
445             foreach my $op (@operators){
446             my @cond = split($op,$cond);
447             $cond[0] =~ s/\s//g; # paramter name without white spaces
448             if(defined $cond[1]){
449             $cond[1] = $1 if($cond[1] =~ m/^\s*\"(.*)\"\s*$/g);
450             push @cond_hash, {
451             'param' => $cond[0],
452             'value' => $cond[1], # undef if == is not in condition
453             'dest' => $dest,
454             'op' => $op,
455             };
456             };
457             }
458             }else{ # unconditioned dest
459             push @cond_hash, {
460             'param' => '',
461             'value' => '', # undef if == is not in condition
462             'dest' => $dest,
463             'op' => '',
464             };
465             }
466             }
467             $invocant->logger->debug("Leaving subroutine get_conditions of $PACKAGE");
468             \@cond_hash;
469             }
470            
471             sub get_dest_id # This method is the first to be called by an application.
472             #For a given activity ID and a set of corresponding paramters produce the next activity ID
473             {
474             my ($invocant,
475             $lib, # 'Kai::Order::Simple'
476             $wfp_id, # 1
477             $wfp_name, # 'EOrder'
478             $wf,$wf_param, # setup paramters
479             # specify starting states for each workflow. Used by SubFlow only
480             $init_act_id, # setup paramter, {'EOrder' => [1],'FillOrder' => [1],'CreditCheck' => [1],}
481             $init_act_id_scalar # concret starting ID, e.g., 10
482             ) = @_;
483             $invocant->logger->debug("Entering subroutine get_dest_id of $PACKAGE");
484             my $xml = $invocant->get_act_element($wfp_id->{$wfp_name},$init_act_id_scalar);
485             my $perl = XMLin($xml);
486             my %perl = %$perl;
487             my @chiave = keys(%perl);
488             my ($restriction,$action,$boolean,@refid); # in case that TransitionRestrictions exist
489             my $dest_unrest;
490             if(grep(/TransitionRestrictions/,@chiave)){
491             my $restr = $perl->{'TransitionRestrictions'}->{'TransitionRestriction'};
492             if(ref $restr->{'Split'}){
493             $action = 'Split';
494             }else{
495             $action = 'Join';
496             }
497             if($restr->{$action}->{'Type'} eq 'XOR'){
498             $boolean = 'XOR';
499             }else{
500             $boolean = 'AND';
501             }
502             my $ref_id = $restr->{$action}->{'TransitionRefs'}->{'TransitionRef'};
503             if($ref_id){
504             my @ref_id;
505             eval{ @ref_id = @$ref_id;};
506             push @ref_id, $ref_id if($@);
507             push @refid, $_->{'Id'} foreach(@ref_id);
508             $restriction = 1;
509             }else{
510             $restriction = 0;
511             }
512             }else{$restriction = 0;}
513             # if there is an implementation, we should call a method which can cause a change in the DataFields
514             if(grep(/Implementation/,@chiave)){
515             print "Implementation step\n";
516             my $subflow = $invocant->get_subflow($wfp_id->{$wfp_name},$init_act_id_scalar);
517             unless($subflow){
518             my $code = $invocant->get_perl_by_act_id($lib->{$wfp_name},$wfp_id->{$wfp_name},$init_act_id_scalar);
519             my $params_new = eval($code); # exe the perl code
520             $invocant->formal_parameters({'EXCEPTION' => {'SYSTEM' => $!,}}) if($@);
521             $invocant->data_fields($params_new)if(ref $params_new); # update $invocant->{DataFields}
522             $dest_unrest = $invocant->get_dest_from_transitions($wfp_id->{$wfp_name},$init_act_id_scalar); # dest list from transitions
523             # if no restriction on transition then go to Transition node
524             unless($restriction){ # lack of restriction: the dest list from transitions are the dest
525             $invocant->logger->debug("Leaving subroutine get_dest_id of $PACKAGE");
526             return $dest_unrest;
527             }else{ # with restrictions
528             $invocant->logger->debug("Leaving subroutine get_dest_id of $PACKAGE");
529             return $invocant->get_dest_id_with_restrictions($wfp_id->{$wfp_name},$boolean,\@refid,$dest_unrest);
530             }
531             }else{ # subprocess
532             # get WF ID
533             #my $wf_id; #TODO
534             #my $wfp_name = $invocant->get_wfpname_by_id($wf_id);
535             #my $out = $wf->{$wfp_name}->start_workflow($wfp_id->{$wfp_name},$wf_param,$init_act_id,$wfp_name);
536             return {}; # no support to Subprocess
537             }
538             }else{ # Route
539             my $code = $invocant->get_perl_by_act_id($lib->{$wfp_name},$wfp_id->{$wfp_name},$init_act_id_scalar);
540             my $params_new = eval($code); # exe the perl code
541             $invocant->formal_parameters({'EXCEPTION' => {'SYSTEM' => $!,}}) if($@);
542             $invocant->data_fields($params_new)if(ref $params_new); # update $invocant->{DataFields}
543             $dest_unrest = $invocant->get_dest_from_transitions($wfp_id->{$wfp_name},$init_act_id_scalar); # dest list from transitions
544             if($restriction){ # with restriction
545             print "Route step\n";
546             $invocant->logger->debug("Leaving subroutine get_dest_id of $PACKAGE");
547             return $invocant->get_dest_id_with_restrictions($wfp_id->{$wfp_name},$boolean,\@refid,$dest_unrest);
548             }else{
549             $invocant->logger->debug("Leaving subroutine get_dest_id of $PACKAGE");
550             return {}; # with Route and without Restriction is wrong
551             }
552             #TODO
553             }
554             }
555            
556            
557             sub get_dest_from_transitions # Return an array of raw destination IDs from the Transitions identified by a 'From' ID
558             {
559             my ($invocant,$wfp_id,$init_act_id) = @_;
560             $invocant->logger->debug("Entering subroutine get_dest_from_transitions of $PACKAGE");
561             my @dest;
562             my $cond = $invocant->get_conditions($wfp_id,$init_act_id);
563             foreach(@$cond){
564             if($_->{'op'} eq '=='){
565             if( $invocant->{DataFields}->{$_->{'param'}} eq $_->{'value'}){
566             push @dest, $_->{'dest'};
567             }
568             }
569             if($_->{'op'} eq '!='){
570             if( $invocant->{DataFields}->{$_->{'param'}} ne $_->{'value'}){
571             push @dest, $_->{'dest'};
572             }
573             }
574             }
575             foreach(@$cond){
576             if($_->{'op'} eq 'OTHERWISE'){ # TODO: 'EXCEPTION' not supported yet
577             push @dest, $_->{'dest'};
578             }
579             }
580             foreach(@$cond){
581             if($_->{'op'} eq ''){
582             push @dest, $_->{'dest'};
583             }
584             }
585             $invocant->logger->debug("Leaving subroutine get_dest_from_transitions of $PACKAGE");
586             return \@dest;
587             }
588            
589             sub get_dest_id_with_restrictions # Controls a list of Transition reference IDs ($refid) and a list of raw destination IDs
590             # to produce the correct destination IDs
591             {
592             my ($invocant,$wfp_id,$boolean,$refid,$dest_unrest) = @_;
593             $invocant->logger->debug("Entering subroutine get_dest_id_with_restrictions of $PACKAGE");
594             my @dest;
595             foreach(@$refid){
596             my $xml = $invocant->get_transition($wfp_id,$_); # get dest id & condition by transition ref
597             if($xml){
598             my $perl = XMLin($xml);
599             my $to = $perl->{'To'};
600             push @dest, $to if(grep(/^$to$/,@$dest_unrest)); # valid only if restriction id in unrestricted list
601             return \@dest if($boolean eq 'XOR' && @dest); # TODO: return the first ID for 'XOR'
602             }
603             }
604             $invocant->logger->debug("Leaving subroutine get_dest_id_with_restrictions of $PACKAGE");
605             return \@dest; # return all for 'AND'
606             }
607            
608             sub get_wfp_element
609             # Produces the WorkflowProcess (specified by workflow name) subnode of workflow configuration file, used by sub init_data_fields
610             {
611             my ($invocant,$wfp_id,$subnode) = @_;
612             $invocant->logger->debug("Entering subroutine get_wfp_element of $PACKAGE");
613             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/|.$subnode); # find all paragraphs
614             foreach my $node ($nodeset->get_nodelist)
615             {
616             $invocant->logger->debug("Leaving subroutine get_wfp_element of $PACKAGE");
617             return XML::XPath::XMLParser::as_string($node);
618             }
619             }
620            
621             sub get_act_element
622             # Produces the Activity (specified by workflow name and Activity ID) subnode of workflow configuration file, used by sub get_act_id
623             {
624             my ($invocant,$wfp_id,$id,) = @_;
625             $invocant->logger->debug("Entering subroutine get_act_element of $PACKAGE");
626             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/Activities/Activity[@Id='|.$id.q|']|); # find all paragraphs
627             foreach my $node ($nodeset->get_nodelist)
628             {
629             $invocant->logger->debug("Leaving subroutine get_act_element of $PACKAGE");
630             return XML::XPath::XMLParser::as_string($node);
631             }
632             }
633            
634             sub get_transition
635             # Produces the Transition (specified by workflow name and Transition ID) subnode of workflow configuration file, used by sub get_dest_id_with_restrictions
636             {
637             my ($invocant,$wfp_id,$id,) = @_;
638             $invocant->logger->debug("Entering subroutine get_transitions of $PACKAGE");
639             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/Transitions/Transition[@Id='|.$id.q|']|); # find all paragraphs
640             foreach my $node ($nodeset->get_nodelist)
641             {
642             $invocant->logger->debug("Leaving subroutine get_transitions of $PACKAGE");
643             return XML::XPath::XMLParser::as_string($node);
644             }
645             }
646            
647             sub get_subflow
648             # Produces the Subflow (specified by workflow name and Activity ID) subnode of workflow configuration file, used by sub get_dest_id
649             {
650             my ($invocant,$wfp_id,$init_act_id,) = @_;
651             $invocant->logger->debug("Entering subroutine get_transitions of $PACKAGE");
652             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']/Activities/Activity[@Id='|.$init_act_id.q|']/Implementation/SubFlow|); # find all SubFlows
653             foreach my $node ($nodeset->get_nodelist)
654             {
655             $invocant->logger->debug("Leaving subroutine get_transitions of $PACKAGE");
656             return XML::XPath::XMLParser::as_string($node);
657             }
658             }
659            
660             sub start_workflow {
661             my ($invocant,
662             $wfp_id, # 1
663             $wf_param,$init_act_id, # setup parameters
664             $wf_name # 'EOrder'
665             ) = @_;
666             $invocant->formal_parameters($wf_param->{$wfp_id->{$wf_name}}->{'IN'});
667             my @init_act_id;
668             eval{ @init_act_id = @{$init_act_id->{$wf_name}};};
669             push @init_act_id, $init_act_id->{$wf_name} if($@);
670             while(1){
671             my @dest_act_id = ();
672             foreach(@init_act_id) {
673             my $dest_act_id = $wf_param->{$wfp_id->{$wf_name}}->{'ACTION'}->{$_}->([$_],[]);
674             goto USCITA unless($dest_act_id); # exist if no destinition
675             eval{@dest_act_id = @$dest_act_id;};
676             goto USCITA if($@); # exit if no destinition
677             if($#dest_act_id > 0) { # multiple dest id
678             print "The next activity IDs are @dest_act_id\n\n";
679             }else{ # single dest id
680             print "The next activity ID is @dest_act_id\n\n";
681             }
682             if(@dest_act_id){
683             @init_act_id = @dest_act_id; # start from arrival
684             }else{
685             print "Process end point reached.\n";
686             goto USCITA; # exist if dest ID is 0
687             }
688             }
689             }
690             USCITA:
691             return $wf_param->{$wfp_id->{$wf_name}}->{'OUT'};
692             }
693            
694            
695             sub formal_parameters # set elements in FormalParameters and retrun a pointer to the FormalParameters
696             {
697             my ($invocant,$fp) = (shift,shift);
698             $invocant->logger->debug("Entering subroutine formal_parameters of $PACKAGE");
699             if(defined $fp){
700             my %fp = %$fp;
701             my @chiave = keys(%fp);
702             foreach(@chiave){
703             $invocant->{FormalParameters}->{$_} = $fp->{$_};
704             }
705             }
706             $invocant->logger->debug("Leaving subroutine formal_parameters of $PACKAGE");
707             return $invocant->{FormalParameters};
708             }
709             sub get_wfpname_by_id
710             # Produces the Transition (specified by workflow name and Transition ID) subnode of workflow configuration file, used by sub get_dest_id_with_restrictions
711             {
712             my ($invocant,$wfp_id) = @_;
713             $invocant->logger->debug("Entering subroutine get_transitions of $PACKAGE");
714             my $nodeset = $CONFIG->find(q|/Package/WorkflowProcesses/WorkflowProcess[@Id='|.$wfp_id.q|']|); # find all paragraphs
715             my $xml;
716             foreach my $node ($nodeset->get_nodelist)
717             {
718             $invocant->logger->debug("Leaving subroutine get_transitions of $PACKAGE");
719             $xml = XML::XPath::XMLParser::as_string($node);
720             last;
721             }
722             my $perl = XMLin($xml);
723             return $perl->{'Name'};
724             }
725             1;
726             __END__