Index: openacs-4/packages/workflow/tcl/action-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/action-procs.tcl,v diff -u -r1.26 -r1.27 --- openacs-4/packages/workflow/tcl/action-procs.tcl 12 Jan 2004 10:58:21 -0000 1.26 +++ openacs-4/packages/workflow/tcl/action-procs.tcl 13 Jan 2004 12:36:47 -0000 1.27 @@ -460,12 +460,6 @@ } } - if { !$internal_p } { - # Flush the workflow cache, as changing an action changes the entire workflow - # e.g. initial_action_p, enabled_in_states. - workflow::flush_cache -workflow_id $workflow_id - } - return $action_id } @@ -1054,10 +1048,6 @@ } } - if { !$internal_p } { - workflow::flush_cache -workflow_id $workflow_id - } - return $action_id } @@ -1317,7 +1307,7 @@ # Get rid of a few defaults array set defaults { initial_action_p f always_enabled_p f } - set spec {} + set spec [list] foreach name [lsort [array names row]] { if { ![empty_string_p $row($name)] && ![exists_and_equal defaults($name) $row($name)] } { lappend spec $name $row($name) Index: openacs-4/packages/workflow/tcl/case-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/case-procs.tcl,v diff -u -r1.22 -r1.23 --- openacs-4/packages/workflow/tcl/case-procs.tcl 13 Jan 2004 09:10:12 -0000 1.22 +++ openacs-4/packages/workflow/tcl/case-procs.tcl 13 Jan 2004 12:36:47 -0000 1.23 @@ -107,6 +107,40 @@ db_transaction { + # If there is no initial-action, we create one now + # TODO: Should we do this here, or throw an error like we used to? + + # Initial action + set initial_action_id [workflow::get_element -workflow_id $workflow_id -element initial_action_id] + + + if { [empty_string_p $initial_action_id] } { + # TODO: This is the old error message, if we want to throw it still, maybe make it optional + # error "The workflow must have an initial action." + + set action_row(pretty_name) "Start" + set action_row(pretty_past_tense) "Started" + set action_row(initial_action_p) "t" + + set states [workflow::fsm::get_states -workflow_id $workflow_id] + + # We use the first state as the initial state + set action_row(new_state_id) [lindex $states 0] + + # Add the new initial action + set initial_action_id [workflow::action::fsm::edit \ + -operation "insert" \ + -array action_row \ + -workflow_id $workflow_id] + } else { + # NOTE: FSM-specific check here + set new_state [workflow::action::fsm::get_element -action_id $initial_action_id -element new_state] + + if { [empty_string_p $new_state] } { + error "Initial action must change state." + } + } + # Insert the case set case_id [insert \ -workflow_id $workflow_id \ @@ -120,25 +154,12 @@ workflow::case::role::assign -case_id $case_id -array assignment_array } - # Initial action - set action_id [workflow::get_element -workflow_id $workflow_id -element initial_action_id] - if { [empty_string_p $action_id] } { - error "The workflow must have an initial action." - } - - # NOTE: FSM-specific check here - set new_state [workflow::action::fsm::get_element -action_id $action_id -element new_state] - - if { [empty_string_p $new_state] } { - error "Initial action must change state." - } - # Execute the initial action workflow::case::action::execute \ -no_notification=$no_notification_p \ -case_id $case_id \ - -action_id $action_id \ + -action_id $initial_action_id \ -comment $comment \ -comment_mime_type $comment_mime_type \ -user_id $user_id \ @@ -188,8 +209,7 @@ workflow::case::fsm::get -case_id $case_id -array row -action_id $action_id - # LARS TODO: - # Should we redesign the API so that it's polymorphic, wrt. to workflow type (FSM/Petri Net) + # TODO: Should we redesign the API so that it's polymorphic, wrt. to workflow type (FSM/Petri Net) # That way, you'd call workflow::case::get and get a state_pretty pseudocolumn, which would be # the pretty-name of the state in an FSM, but it would be some kind of human-readable summary of # the active tokens in a petri net. Index: openacs-4/packages/workflow/tcl/role-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/role-procs.tcl,v diff -u -r1.15 -r1.16 --- openacs-4/packages/workflow/tcl/role-procs.tcl 17 Dec 2003 14:02:41 -0000 1.15 +++ openacs-4/packages/workflow/tcl/role-procs.tcl 13 Jan 2004 12:36:47 -0000 1.16 @@ -257,12 +257,6 @@ } } - if { !$internal_p } { - # Flush the workflow cache, as changing an role changes the entire workflow - # e.g. initial_role_p, enabled_in_states. - workflow::flush_cache -workflow_id $workflow_id - } - return $role_id } Index: openacs-4/packages/workflow/tcl/state-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/state-procs.tcl,v diff -u -r1.10 -r1.11 --- openacs-4/packages/workflow/tcl/state-procs.tcl 17 Dec 2003 14:02:41 -0000 1.10 +++ openacs-4/packages/workflow/tcl/state-procs.tcl 13 Jan 2004 12:36:47 -0000 1.11 @@ -252,12 +252,6 @@ } } - if { !$internal_p } { - # Flush the workflow cache, as changing an state changes the entire workflow - # e.g. initial_state_p, enabled_in_states. - workflow::flush_cache -workflow_id $workflow_id - } - return $state_id } Index: openacs-4/packages/workflow/tcl/workflow-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/workflow-procs.tcl,v diff -u -r1.19 -r1.20 --- openacs-4/packages/workflow/tcl/workflow-procs.tcl 9 Jan 2004 15:47:53 -0000 1.19 +++ openacs-4/packages/workflow/tcl/workflow-procs.tcl 13 Jan 2004 12:36:47 -0000 1.20 @@ -527,10 +527,12 @@ ad_proc -public workflow::generate_spec { {-workflow_id:required} + {-workflow_handler "workflow"} {-handlers { roles workflow::role actions workflow::action }} + {-deep:boolean} } { Generate a spec for a workflow in array list style. Note that calling this directly with the default arguments will bomb, because workflow::action doesn't implement the required API. @@ -572,20 +574,57 @@ } } + set child_workflows [list] + foreach { key namespace } $handlers { set subspec [list] foreach sub_id [${namespace}::get_ids -workflow_id $workflow_id] { set sub_short_name [${namespace}::get_element \ -one_id $sub_id \ -element short_name] - lappend subspec $sub_short_name [${namespace}::generate_spec -one_id $sub_id] + set elm_spec [${namespace}::generate_spec -one_id $sub_id] + + if { $deep_p } { + if { [string equal $key "actions"] } { + array unset elm_array + array set elm_array $elm_spec + if { [exists_and_not_null elm_array(child_workflow)] } { + # Prefix the child workflow with the short_name of the parent workflow + set new_child_workflow ${short_name}_$elm_array(child_workflow) + + # Change the child_workflow to the prefixed version in the spec + set elm_array(child_workflow) $new_child_workflow + + # Output the modified spec + set elm_spec [list] + foreach name [lsort [array names elm_array]] { + lappend elm_spec $name $elm_array($name) + } + + # Remember this child workflow, so we generate the spec for it later + set child_workflow_id [${namespace}::get_element -one_id $sub_id -element child_workflow_id] + lappend child_workflows $child_workflow_id $new_child_workflow + } + } + } + + lappend subspec $sub_short_name $elm_spec } - lappend spec $key $subspec } - return [list $short_name $spec] + set spec [list $short_name $spec] + + foreach { child_workflow_id new_short_name } $child_workflows { + set child_spec [${workflow_handler}::generate_spec \ + -workflow_id $child_workflow_id \ + -workflow_handler $workflow_handler \ + -handlers $handlers] + set spec [concat $spec $new_short_name [list [lindex $child_spec 1]]] + } + + return $spec } ad_proc -public workflow::clone { @@ -594,6 +633,7 @@ {-object_id {}} {-array {}} {-workflow_handler workflow} + {-deep:boolean} } { Clones an existing FSM workflow. The clone must belong to either a package key or an object id. @@ -618,8 +658,10 @@ } set spec [${workflow_handler}::generate_spec \ - -workflow_id $workflow_id] - + -workflow_id $workflow_id \ + -workflow_handler $workflow_handler \ + -deep=$deep_p] + set workflow_id [${workflow_handler}::new_from_spec \ -package_key $package_key \ -object_id $object_id \ @@ -659,13 +701,20 @@ @author Lars Pind (lars@collaboraid.biz) @see workflow::new } { - if { [llength $spec] != 2 } { - error "A workflow spec must have exactly two elements, short_name and an array-list with details." + if { [llength $spec] > 2 } { + # Create any additional (child) workflows first, so they're available when creating the main one below + # Not passing in the array, not keeping the workflow_id + ${workflow_handler}::new_from_spec \ + -package_key $package_key \ + -object_id $object_id \ + -spec [lrange $spec 2 end] \ + -workflow_handler $workflow_handler \ + -handlers $handlers } set short_name [lindex $spec 0] array set workflow_array [lindex $spec 1] - + # Override workflow attributes from the array if { ![empty_string_p $array] } { upvar 1 $array row @@ -761,7 +810,6 @@ set row($key) [string trim $row($key)] } -# ns_log Notice "LARS: ${namespace}::edit -- short_name $row(short_name) -- [array get row] -- [db_list select_roles { select short_name from workflow_roles where workflow_id = :workflow_id }]" ${namespace}::edit \ -internal \ -operation "insert" \ @@ -1049,6 +1097,13 @@ ad_proc -public workflow::fsm::generate_spec { {-workflow_id:required} + {-workflow_handler "workflow"} + {-handlers { + roles workflow::role + states workflow::state::fsm + actions workflow::action::fsm + }} + {-deep:boolean} } { Generate a spec for a workflow in array list style. @@ -1060,11 +1115,9 @@ } { set spec [workflow::generate_spec \ -workflow_id $workflow_id \ - -handlers { - roles workflow::role - states workflow::state::fsm - actions workflow::action::fsm - }] + -workflow_handler $workflow_handler \ + -handlers $handlers \ + -deep=$deep_p] return $spec }