# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl Workflow-Wfmc.t' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test::More tests => 2; BEGIN { use_ok('Workflow::Wfmc') }; ######################### use strict; use warnings; use XML::Simple qw|XMLin XMLout|; use Data::Dumper; use XML::XPath::XMLParser; use Workflow::Wfmc; # my workflow class use Getopt::Long; ####################### Usage instruction ########################## our ($opt_help,$opt_file,$opt_conf,$opt_ordertype,$opt_ordern,$opt_actno,$opt_total); my $num_arg = $#ARGV; Getopt::Long::Configure("bundling"); GetOptions("file|f=s", "conf|c=s","ordertype|t=s","ordern|n=s","actno|a=s","total|l=s", "help|?"); #if ($num_arg < 0 || defined($opt_help)) { if (0) { # substitute this line withe the above when run directly printf <<'END'; Usage: Runable.pm [OPTIONS] Exchange orders between nodes and update DB. -f, --file="/path/to/order.xml" order file path -c, --conf="C:/kai/PERL/Kai-Workflow/workflow.xml" configuration file path -t, --ordertype="PO" order type "PO" or "Credit" -n, --ordern="EP100" order number, e.g., "EP100" -a, --actno="10100126" account number, e.g., "EP100" -l, --total="200" total amount in EURO, e.g., 120 --help display this help and exit END exit(0); } ####### START: arguments ####### my $order_file = defined($opt_file) ? $opt_file :'./lib/Workflow/Wfmc/Test/sample_order.xml'; # defaults to Kai's setup my $conf_file = defined($opt_conf) ? $opt_conf :'./lib/Workflow/Wfmc/Test/workflow.xml'; # defaults to Kai's setup my $order_type = defined($opt_ordertype) ? $opt_ordertype :'PO'; # defaults to Kai's setup my $order_ordern= defined($opt_ordern) ? $opt_ordern :'EP100'; # defaults to Kai's setup my $order_actno = defined($opt_actno) ? $opt_actno :'10100126'; # defaults to Kai's setup my $order_total = defined($opt_total) ? $opt_total :'200'; # defaults to Kai's setup ####### END: arguments ######### open(IN,"<$order_file"); my $doc = do{local $/;;}; # slurp an approvable close(IN); my $init_act_id = { # specify starting states for each workflow 'EOrder' => [1], 'FillOrder' => [1], 'CreditCheck' => [1], }; my $wfp_id = { # These are the workflow process IDs 'EOrder' => "1", 'FillOrder' => "2", 'CreditCheck' => "3", }; my $cust_lib = # list customized libraries used to handle call-backs { 'EOrder' =>'Workflow::Wfmc::Test::Order', # class to handle EOrder workflow 'FillOrder' =>'Workflow::Wfmc::Test::Order', # class to handle FillOrder workflow 'CreditCheck' =>'Workflow::Wfmc::Test::Order', # class to handle Credit workflow }; my $wf = { # create workflow objects first 'EOrder' => new Workflow::Wfmc('Id' => $wfp_id->{'EOrder'}), 'FillOrder' => new Workflow::Wfmc('Id' => $wfp_id->{'FillOrder'}), 'CreditCheck' => new Workflow::Wfmc('Id' => $wfp_id->{'CreditCheck'}), }; $wf->{'EOrder'} ->load_conf($conf_file); # load the workflow config file $wf->{'FillOrder'} ->load_conf($conf_file); # load the workflow config file $wf->{'CreditCheck'} ->load_conf($conf_file); # load the workflow config file my $data_fields = { # initialize the process variables: data fields 'EOrder' => $wf->{'EOrder'} ->init_data_fields($wfp_id->{'EOrder'}), 'FillOrder' => $wf->{'FillOrder'} ->init_data_fields($wfp_id->{'FillOrder'}), 'CreditCheck' => $wf->{'CreditCheck'}->init_data_fields($wfp_id->{'CreditCheck'}), }; # The following pointer contains the entire workflow configuration, including call-back functions (ACTION) # Attention: The following paramter refers to itself when calling sub get_dest_id() my $wf_param = {}; # initialize the process input/output parametrs, $wf_param = { # process exceptions and call-back functions (actions) $wfp_id->{'EOrder'} => # workflow ID { 'IN' => { 'orderString' => 'AAA', # FormalParameters of workflow }, 'OUT' => { 'returnMessage' => '', # FormalParameters of workflow }, 'EXCEPTION' => # defined by Kai { 'SYSTEM' => { }, 'APPLICATION' => { }, }, 'ACTION' => # call-back functions (Activity/Implementation/Tool) { '0' => sub { print "The activity number '0' is under construction...\n"; return {}; }, '1' => sub { $data_fields = $wf->{'EOrder'}->data_fields({'orderInfo' => $doc,}); return &init2dest(shift,shift,'EOrder'); }, '6' => sub { print "All done. Existing...\n"; return {}; }, '8' => sub { print "The activity number '8' is under construction...\n"; return {}; }, '9' => sub { return &init2dest(shift,shift,'EOrder'); }, '10' => sub { print "Subprocess \"Checking Credit\" reached.\n"; print "The activity number '10' is under construction...\n"; return {}; }, '11' => sub { print "The activity number '11' is under construction...\n"; return {}; }, '12' => sub { $data_fields->{'EOrder'} = $wf->{'EOrder'}->data_fields({'orderType' => $order_type,});# modify $DATAFIELDS, 'Credit' or 'PO' return &init2dest(shift,shift,'EOrder'); }, '32' => sub { $data_fields->{'EOrder'} = $wf->{'EOrder'}->data_fields({'orderInfo' => $doc,'orderNumber' => $order_ordern,});# modify $DATAFIELDS return &init2dest(shift,shift,'EOrder'); }, '39' => sub { $data_fields->{'EOrder'} = $wf->{'EOrder'}->data_fields({'orderNumber' => $order_ordern,});# modify $DATAFIELDS return &init2dest(shift,shift,'EOrder'); }, '41' => sub { $data_fields->{'EOrder'} = $wf->{'EOrder'}->data_fields({'orderInfo.AccountNumber' => $order_actno,'orderInfo.ToltalAmount' => $order_total});# modify $DATAFIELDS, 'Credit' or 'PO' return &init2dest(shift,shift,'EOrder'); }, '56' => sub { print "The activity number '56' is under construction...\n"; return {}; }, }, }, $wfp_id->{'FillOrder'} => # workflow ID { 'IN' => { 'orderString' => 'BBB', }, 'OUT' => { 'returnMessage' => '', }, 'EXCEPTION' => { 'SYSTEM' => { }, 'APPLICATION' => { }, }, 'ACTION' => { '0' => sub { print "The activity number is under construction...\n"; return {}; }, '1' => sub { $data_fields = $wf->{'FillOrder'}->data_fields({'orderInfo' => $doc,});# modify $DATAFIELDS return &init2dest(shift,shift,'FillOrder'); }, }, }, $wfp_id->{'CreditCheck'} => # workflow ID { 'IN' => { 'orderString' => 'CCC', }, 'OUT' => { 'returnMessage' => '', }, 'EXCEPTION' => { 'SYSTEM' => { }, 'APPLICATION' => { }, }, 'ACTION' => { '0' => sub { print "The activity number is under construction...\n"; return {}; }, '1' => sub { $data_fields = $wf->{'CreditCheck'}->data_fields({'orderInfo' => $doc,});# modify $DATAFIELDS return &init2dest(shift,shift,'CreditCheck'); }, }, }, }; ######### Finished definition, starting workflow engine ######################### print "The starting activity ID is $init_act_id->{'EOrder'}->[0]\n\n"; my $out = $wf->{'EOrder'}->start_workflow($wfp_id,$wf_param,$init_act_id,'EOrder'); ok($out, "end"); sub init2dest { my ($init_act_id,$dest_act_id,$wfp_name) = (shift,shift,shift); my @dest_act_id; eval{@dest_act_id = @$dest_act_id;}; @dest_act_id = () if($@); # modify $DATAFIELDS in the following way: slurping a purchase order # for a given activity ID and a set of corresponding paramters produce the next activity ID foreach(@$init_act_id){ # TODO: using thread to make parallel calculations my $dest_id = $wf->{$wfp_name}->get_dest_id($cust_lib,$wfp_id,$wfp_name,$wf,$wf_param,$init_act_id,$_); push @dest_act_id, @$dest_id; # and acumulate new destination IDs } return \@dest_act_id; }