WCM submit (for approval) workflow.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4540 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2006-12-07 00:05:28 +00:00
parent b8bfe273b4
commit 1ee6547fc4
8 changed files with 353 additions and 80 deletions

View File

@@ -169,6 +169,7 @@
<prop key="redeploy">false</prop>
</props>
<props>
<!-- WCM workflow definition -->
<prop key="engineId">jbpm</prop>
<prop key="location">alfresco/workflow/submit_processdefinition.xml</prop>
<prop key="mimetype">text/xml</prop>
@@ -178,12 +179,14 @@
</property>
<property name="models">
<list>
<value>alfresco/workflow/workflowModel.xml</value>
<value>alfresco/workflow/workflowModel.xml</value>
<value>alfresco/workflow/wcmWorkflowModel.xml</value>
</list>
</property>
<property name="labels">
<list>
<value>alfresco/workflow/workflow-messages</value>
<value>alfresco/workflow/workflow-messages</value>
<value>alfresco/workflow/wcm-workflow-messages</value>
</list>
</property>
</bean>

View File

@@ -59,7 +59,7 @@
</bean>
<!-- MBeanServer Connector (registers itself with custom alfrescoMBeanServer) -->
<bean id="serverConnector"
<!-- <bean id="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean"
depends-on="registry">
@@ -69,7 +69,6 @@
<property name="environment">
<map>
<!-- The following keys are only valid when sun jmx is used -->
<entry key="jmx.remote.x.password.file" value="${alfresco.jmx.dir}/alfresco-jmxrmi.password"/>
<entry key="jmx.remote.x.access.file" value="${alfresco.jmx.dir}/alfresco-jmxrmi.access"/>
</map>
@@ -80,11 +79,11 @@
<property name="server" ref="alfrescoMBeanServer"/>
<property name="beans">
<map>
<!-- MBeans to register with alfrescoMBeanServer -->
<entry key="Alfresco:Name=VirtServerRegistry,Type=VirtServerRegistry" value-ref="VirtServerRegistry"/>
</map>
</property>
</bean>
-->
<!-- MBeans registered with alfrescoMBeanServer -->
<bean id="VirtServerRegistry"

View File

@@ -1,28 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This describes a process for submitting changed content in a user -->
<!-- sandbox, via an approver, to the staging sandbox. -->
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:submit">
<swimlane name="initiator"/>
<start-state name="start">
<task name="wf:submitWebContentTask" swimlane="initiator"/>
<transition name="" to="review"/>
</start-state>
<swimlane name="assignee">
<assignment actor-id="#{bpm_assignee.properties['cm:userName']}"/>
</swimlane>
<task-node name="review">
<task name="wf:reviewTask" swimlane="assignee"/>
<transition name="Approve" to="end">
<action class="org.alfresco.repo.avm.wf.AVMSubmitPackageHandler"/>
</transition>
</task-node>
<end-state name="end"/>
<?xml version="1.0" encoding="UTF-8"?>
<!-- This describes a process for submitting changed content in a user -->
<!-- sandbox, via an approver, to the staging sandbox. -->
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wcmwf:submit">
<swimlane name="initiator"/>
<!-- -->
<!-- Start Review -->
<!-- -->
<start-state name="start">
<task name="wcmwf:submitReviewTask" swimlane="initiator"/>
<transition name="" to="serialorparallel"/>
<event type="node-leave">
<script>
<variable name="wcmwf_reviewerCnt" access="write"/>
<variable name="wcmwf_approveCnt" access="write"/>
<expression>
wcmwf_reviewerCnt = bpm_assignees.size();
wcmwf_approveCnt = 0;
</expression>
</script>
</event>
</start-state>
<!-- -->
<!-- Split into Serial or Parallel Review -->
<!-- -->
<decision name="serialorparallel">
<transition name="serial" to="submitserialreview" />
<transition name="parallel" to="submitparallelreview">
<condition>#{wcmwf_reviewType == "Parallel"}</condition>
</transition>
</decision>
<!-- -->
<!-- Serial Review -->
<!-- -->
<decision name="submitserialreview">
<transition name="endreview" to="endreview" />
<transition name="review" to="serialreview">
<condition>#{wcmwf_approveCnt &lt; wcmwf_reviewerCnt}</condition>
</transition>
</decision>
<task-node name="serialreview">
<task name="wcmwf:reviewTask">
<event type="task-create">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
taskInstance.actorId = bpm_assignees.get(wcmwf_approveCnt).properties.userName;
</script>
</action>
</event>
</task>
<transition name="reject" to="endreview" />
<transition name="approve" to="submitserialreview">
<script>
<variable name="wcmwf_approveCnt" access="read, write"/>
<expression>
wcmwf_approveCnt = wcmwf_approveCnt + 1;
</expression>
</script>
</transition>
</task-node>
<!-- -->
<!-- Parallel Review -->
<!-- -->
<node name="submitparallelreview">
<action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
<foreach>#{bpm_assignees}</foreach>
<var>reviewer</var>
</action>
<transition name="review" to="parallelreview" />
</node>
<task-node name="parallelreview">
<task name="wcmwf:reviewTask">
<event type="task-create">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
taskInstance.actorId = reviewer.properties["cm:userName"];
</script>
</action>
</event>
</task>
<transition name="reject" to="joinparallelreview" />
<transition name="approve" to="joinparallelreview">
<script>
<variable name="wcmwf_approveCnt" access="read,write" />
<expression>
wcmwf_approveCnt = wcmwf_approveCnt +1;
</expression>
</script>
</transition>
</task-node>
<join name="joinparallelreview">
<transition to="endreview" />
</join>
<!-- -->
<!-- End the Review -->
<!-- -->
<decision name="endreview">
<transition name="rejected" to="rejected" />
<transition name="approved" to="approved">
<condition>#{wcmwf_approveCnt == wcmwf_reviewerCnt}</condition>
<action class="org.alfresco.repo.avm.wf.AVMSubmitPackageHandler"/>
</transition>
</decision>
<task-node name="rejected">
<task name="wcmwf:rejectedTask" swimlane="initiator" />
<transition name="" to="end" />
</task-node>
<task-node name="approved">
<task name="wcmwf:approvedTask" swimlane="initiator" />
<transition name="" to="end" />
</task-node>
<!-- -->
<!-- End the Process -->
<!-- -->
<end-state name="end"/>
</process-definition>

View File

@@ -0,0 +1,38 @@
# Display labels for out-of-the-box WCM Content-oriented Workflows
#
# Submit Workflow
#
wcmwf_submit.workflow.title=Web Site Submission
wcmwf_submit.workflow.description=Submit changes for approval
wcmwf_submit.node.serialreview.transition.reject.title=Reject
wcmwf_submit.node.serialreview.transition.reject.description=Reject
wcmwf_submit.node.serialreview.transition.approve.title=Approve
wcmwf_submit.node.serialreview.transition.approve.description=Approve
wcmwf_submit.node.parallelreview.transition.reject.title=Reject
wcmwf_submit.node.parallelreview.transition.reject.description=Reject
wcmwf_submit.node.parallelreview.transition.approve.title=Approve
wcmwf_submit.node.parallelreview.transition.approve.description=Approve
# Submit Task Definitions
wcmwf_workflowmodel.type.wcmwf_submitReviewTask.title=Web Site Submission
wcmwf_workflowmodel.type.wcmwf_submitReviewTask.description=Submit changes for approval
wcmwf_workflowmodel.type.wcmwf_reviewTask.title=Review
wcmwf_workflowmodel.type.wcmwf_reviewTask.description=Review Documents to approve or reject them
wcmwf_workflowmodel.type.wcmwf_rejectedTask.title=Rejected
wcmwf_workflowmodel.type.wcmwf_rejectedTask.description=Rejected
wcmwf_workflowmodel.type.wcmwf_approvedTask.title=Approved
wcmwf_workflowmodel.type.wcmwf_approvedTask.description=Approved
wcmwf_workflowmodel.property.wcmwf_reviewType.title=Type of Review
wcmwf_workflowmodel.property.wcmwf_reviewType.description=Serial or parallel review
wcmwf_workflowmodel.property.wcmwf_fromPath.title=Source Folder Path
wcmwf_workflowmodel.property.wcmwf_fromPath.description=Folder Path where items have been submitted from
wcmwf_workflowmodel.property.wcmwf_label.title=Submission Label
wcmwf_workflowmodel.property.wcmwf_label.description=Label associated with the submission
wcmwf_workflowmodel.property.wcmwf_reviewerCnt.title=Total Reviewed
wcmwf_workflowmodel.property.wcmwf_reviewerCnt.description=Count of people who reviewed
wcmwf_workflowmodel.property.wcmwf_approveCnt.title=Total Approved
wcmwf_workflowmodel.property.wcmwf_approveCnt.description=Count of people who approved

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<model name="wcmwf:workflowmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
</imports>
<namespaces>
<namespace uri="http://www.alfresco.org/model/wcmworkflow/1.0" prefix="wcmwf"/>
</namespaces>
<constraints>
<constraint name="wcmwf:reviewType" type="LIST">
<parameter name="allowedValues">
<!-- TODO: Determine if priority values can be mapped to human-readable strings -->
<list>
<value>Serial</value>
<value>Parallel</value>
</list>
</parameter>
</constraint>
</constraints>
<types>
<!-- -->
<!-- Base WCM "start" task & workflow task definitions -->
<!-- -->
<!-- Note: Useful for dispatching WCM specific -->
<!-- behaviour -->
<!-- -->
<type name="wcmwf:startTask">
<parent>bpm:startTask</parent>
</type>
<type name="wcmwf:workflowTask">
<parent>bpm:workflowTask</parent>
</type>
<!-- -->
<!-- WCM Tasks -->
<!-- -->
<type name="wcmwf:submitReviewTask">
<parent>wcmwf:startTask</parent>
<mandatory-aspects>
<aspect>wcmwf:reviewType</aspect>
<aspect>wcmwf:submission</aspect>
<aspect>bpm:assignees</aspect>
</mandatory-aspects>
</type>
<type name="wcmwf:reviewTask">
<parent>wcmwf:workflowTask</parent>
<mandatory-aspects>
<aspect>wcmwf:submission</aspect>
<!-- One or more reviewers - this is here to allow view of all reviewers -->
<!-- in the review task -->
<aspect>wcmwf:reviewType</aspect>
<aspect>bpm:assignees</aspect>
</mandatory-aspects>
</type>
<type name="wcmwf:rejectedTask">
<parent>wcmwf:workflowTask</parent>
<mandatory-aspects>
<aspect>wcmwf:reviewType</aspect>
<aspect>bpm:assignees</aspect>
<aspect>wcmwf:reviewStats</aspect>
</mandatory-aspects>
</type>
<type name="wcmwf:approvedTask">
<parent>wcmwf:workflowTask</parent>
<mandatory-aspects>
<aspect>wcmwf:reviewType</aspect>
<aspect>bpm:assignees</aspect>
<aspect>wcmwf:reviewStats</aspect>
</mandatory-aspects>
</type>
</types>
<aspects>
<aspect name="wcmwf:submission">
<properties>
<property name="wcmwf:fromPath">
<title>Source Folder Path</title>
<description>Folder where items have been submitted from</description>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wcmwf:label">
<title>Snapshot Label</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
</properties>
</aspect>
<aspect name="wcmwf:reviewType">
<properties>
<property name="wcmwf:reviewType">
<title>Serial or Parallel Review</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>Serial</default>
<constraints>
<constraint ref="wcmwf:reviewType" />
</constraints>
</property>
</properties>
</aspect>
<aspect name="wcmwf:reviewStats">
<properties>
<property name="wcmwf:reviewerCnt">
<title>Reviewer Count</title>
<type>d:int</type>
<mandatory>true</mandatory>
</property>
<property name="wcmwf:approveCnt">
<title>Approver Count</title>
<type>d:int</type>
<mandatory>true</mandatory>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -11,7 +11,6 @@ import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.Pair;
import org.jbpm.graph.exe.ExecutionContext;
import org.springframework.beans.factory.BeanFactory;
@@ -31,10 +30,6 @@ public class AVMSubmitPackageHandler extends JBPMSpringActionHandler implements
*/
private AVMSyncService fAVMSyncService;
/**
* The NodeService reference.
*/
private NodeService fNodeService;
/**
* Initialize service references.
@@ -45,7 +40,6 @@ public class AVMSubmitPackageHandler extends JBPMSpringActionHandler implements
{
fAVMService = (AVMService)factory.getBean("AVMService");
fAVMSyncService = (AVMSyncService)factory.getBean("AVMSyncService");
fNodeService = (NodeService)factory.getBean("NodeService");
}
/**
@@ -54,48 +48,25 @@ public class AVMSubmitPackageHandler extends JBPMSpringActionHandler implements
*/
public void execute(ExecutionContext executionContext) throws Exception
{
// TODO: Allow submit parameters to passed into this action handler
// rather than pulling directly from execution context
NodeRef pkg = ((JBPMNode)executionContext.getContextInstance().getVariable("bpm_package")).getNodeRef();
Pair<Integer, String> pkgPath = AVMNodeConverter.ToAVMVersionPath(pkg);
// submit the package changes
String description = (String)executionContext.getContextInstance().getVariable("bpm_workflowDescription");
String tag = (String)executionContext.getContextInstance().getVariable("wcmwf_label");
AVMNodeDescriptor pkgDesc = fAVMService.lookup(pkgPath.getFirst(), pkgPath.getSecond());
String targetPath = pkgDesc.getIndirection();
List<AVMDifference> diff = fAVMSyncService.compare(pkgPath.getFirst(), pkgPath.getSecond(), -1, targetPath, null);
fAVMSyncService.update(diff, null, true, true, false, false, null, null);
fAVMSyncService.update(diff, null, true, true, false, false, tag, description);
String from = (String)executionContext.getContextInstance().getVariable("wf_from");
fAVMSyncService.flatten(from, targetPath);
// List<ChildAssociationRef> children = fNodeService.getChildAssocs(pkg);
// List<AVMDifference> diffs = new ArrayList<AVMDifference>();
// Map<String, String> storesHit = new HashMap<String, String>();
// for (ChildAssociationRef child : children)
// {
// NodeRef childRef = child.getChildRef();
// if (!fNodeService.hasAspect(childRef, ContentModel.ASPECT_REFERENCES_NODE))
// {
// throw new AVMSyncException("Package node does not have cm:referencesnode.");
// }
// NodeRef toSubmit = (NodeRef)fNodeService.getProperty(childRef, ContentModel.PROP_NODE_REF);
// Pair<Integer, String> versionPath = AVMNodeConverter.ToAVMVersionPath(toSubmit);
// String avmPath = versionPath.getSecond();
// String [] storePath = avmPath.split(":");
// String websiteName = fAVMService.getStoreProperty(storePath[0],
// QName.createQName(null, ".website.name")).
// getStringValue();
// String stagingName = websiteName + "-staging";
// AVMDifference diff =
// new AVMDifference(-1, avmPath,
// -1, stagingName + ":" + storePath[1],
// AVMDifference.NEWER);
// diffs.add(diff);
// storesHit.put(storePath[0], stagingName);
// }
// // TODO fix update comments if needed.
// fAVMSyncService.update(diffs, true, true, false, false, null, null);
// for (Map.Entry<String, String> entry : storesHit.entrySet())
// {
// fAVMSyncService.flatten(entry.getKey() + ":/appBase",
// entry.getValue() + ":/appBase");
// }
// flatten source folder where changes were submitted from
String from = (String)executionContext.getContextInstance().getVariable("wcmwf_fromPath");
if (from != null && from.length() > 0)
{
fAVMSyncService.flatten(from, targetPath);
}
}
}

View File

@@ -42,9 +42,9 @@ public class TestModel
bootstrapModels.add("alfresco/model/dictionaryModel.xml");
bootstrapModels.add("alfresco/model/systemModel.xml");
bootstrapModels.add("alfresco/model/contentModel.xml");
bootstrapModels.add("alfresco/model/wcmModel.xml");
bootstrapModels.add("alfresco/model/applicationModel.xml");
bootstrapModels.add("alfresco/model/bpmModel.xml");
bootstrapModels.add("alfresco/workflow/workflowModel.xml");
// include models specified on command line
for (String arg: args)

View File

@@ -187,7 +187,7 @@ public class WorkflowInterpreter
try
{
String line = fIn.readLine();
if (line.equals("exit"))
if (line.equals("exit") || line.equals("quit"))
{
return;
}
@@ -347,13 +347,17 @@ public class WorkflowInterpreter
return "Syntax Error. Workflow Id not specified.\n";
}
List<WorkflowPath> paths = workflowService.getWorkflowPaths(workflowId);
if (paths.size() == 0)
{
out.println("no further transitions");
}
for (WorkflowPath path : paths)
{
out.println("path: " + path.id + " , node: " + path.node.name + " , active: " + path.active);
List<WorkflowTask> tasks = workflowService.getTasksForWorkflowPath(path.id);
for (WorkflowTask task : tasks)
{
out.println(" task id: " + task.id + " , name: " + task.name + " , properties: " + task.properties.size());
out.println(" task id: " + task.id + " , name: " + task.name + ", title: " + task.title + " , desc: " + task.description + " , properties: " + task.properties.size());
}
for (WorkflowTransition transition : path.node.transitions)
{
@@ -564,8 +568,9 @@ public class WorkflowInterpreter
return "Workflow definition not selected.\n";
}
WorkflowPath path = workflowService.startWorkflow(currentWorkflowDef.id, params);
out.println("started workflow id: " + path.instance.id + ", path: " + path.id + " , node: " + path.node.name + " , def: " + path.instance.definition.title);
out.println("started workflow id: " + path.instance.id + " , def: " + path.instance.definition.title);
currentPath = path;
out.print(interpretCommand("show transitions"));
}
else if (command[0].equals("update"))
@@ -619,7 +624,8 @@ public class WorkflowInterpreter
return "Syntax Error.\n";
}
WorkflowPath path = workflowService.signal(command[1], (command.length == 3) ? command[2] : null);
out.println("signal sent - path id: " + path.id + " , node: " + path.node.name);
out.println("signal sent - path id: " + path.id);
out.print(interpretCommand("show transitions"));
}
else if (command[0].equals("end"))
@@ -631,7 +637,8 @@ public class WorkflowInterpreter
if (command[1].equals("task"))
{
WorkflowTask task = workflowService.endTask(command[2], (command.length == 4) ? command[3] : null);
out.println("signal sent - path id: " + task.path.id + " , node: " + task.path.node.name);
out.println("signal sent - path id: " + task.path.id);
out.print(interpretCommand("show transitions"));
}
else if (command[1].equals("workflow"))
{
@@ -642,6 +649,7 @@ public class WorkflowInterpreter
}
workflowService.cancelWorkflow(workflowId);
out.println("cancelled workflow" + workflowId);
out.print(interpretCommand("show transitions"));
}
else
{