diff --git a/config/alfresco/messages/bpm-messages.properties b/config/alfresco/messages/bpm-messages.properties index 5fecac839f..8a8886cb2d 100644 --- a/config/alfresco/messages/bpm-messages.properties +++ b/config/alfresco/messages/bpm-messages.properties @@ -28,7 +28,6 @@ bpm_businessprocessmodel.association.bpm_pooledActors.title=Pooled Users bpm_businessprocessmodel.association.bpm_pooledActors.title=The users who may take ownership of the task # Workflow Task - bpm_businessprocessmodel.type.bpm_workflowTask.title=Worflow Task bpm_businessprocessmodel.type.bpm_workflowTask.description=Task assigned by a Workflow bpm_businessprocessmodel.property.bpm_workflowDefinitionId.title=Workflow Definition Id diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml index 0a8f5871d8..71ca8e5bd1 100644 --- a/config/alfresco/workflow-context.xml +++ b/config/alfresco/workflow-context.xml @@ -45,6 +45,22 @@ + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuter.java b/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuter.java new file mode 100644 index 0000000000..0aa6c80b6d --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuter.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.workflow; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * Simple workflow action executor + * + * @author Roy Wetherall + */ +public class StartWorkflowActionExecuter extends ActionExecuterAbstractBase +{ + public static final String NAME = "start-workflow"; + + public static final String PARAM_WORKFLOW_NAME = "workflowName"; + + // action dependencies + private NamespaceService namespaceService; + private WorkflowService workflowService; + private NodeService nodeService; + + + /** + * @param namespaceService + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param nodeService + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param workflowService + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#getAdhocPropertiesAllowed() + */ + @Override + protected boolean getAdhocPropertiesAllowed() + { + return true; + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add(new ParameterDefinitionImpl(PARAM_WORKFLOW_NAME, DataTypeDefinition.TEXT, false, getParamDisplayLabel(PARAM_WORKFLOW_NAME))); + // TODO: Start Task Template parameter + } + + + /* (non-Javadoc) + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) + { + // retrieve workflow definition + String workflowName = (String)ruleAction.getParameterValue(PARAM_WORKFLOW_NAME); + WorkflowDefinition def = workflowService.getDefinitionByName(workflowName); + + // create workflow package to contain actioned upon node + NodeRef workflowPackage = (NodeRef)ruleAction.getParameterValue(WorkflowModel.ASSOC_PACKAGE.toPrefixString(namespaceService)); + workflowPackage = workflowService.createPackage(workflowPackage); + ChildAssociationRef childAssoc = nodeService.getPrimaryParent(actionedUponNodeRef); + nodeService.addChild(workflowPackage, actionedUponNodeRef, ContentModel.ASSOC_CONTAINS, childAssoc.getQName()); + + // build map of workflow start task parameters + Map paramValues = ruleAction.getParameterValues(); + Map workflowParameters = new HashMap(); + workflowParameters.put(WorkflowModel.ASSOC_PACKAGE, workflowPackage); + for (Map.Entry entry : paramValues.entrySet()) + { + if (!entry.getKey().equals(PARAM_WORKFLOW_NAME)) + { + QName qname = QName.createQName(entry.getKey(), namespaceService); + Serializable value = entry.getValue(); + workflowParameters.put(qname, value); + } + } + + // start the workflow + workflowService.startWorkflow(def.id, workflowParameters); + } + +} diff --git a/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuterTest.java b/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuterTest.java new file mode 100644 index 0000000000..c9e271362a --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/StartWorkflowActionExecuterTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.workflow; + +import java.util.Date; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.action.ActionImpl; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.BaseSpringTest; +import org.alfresco.util.GUID; + +/** + * Add features action execution test + * + * @author Roy Wetherall + */ +public class StartWorkflowActionExecuterTest extends BaseSpringTest +{ + private NodeService nodeService; + private NamespaceService namespaceService; + private PersonService personService; + private NodeRef rootNodeRef; + private NodeRef nodeRef; + private StartWorkflowActionExecuter executer; + + + /** + * Called at the begining of all tests + */ + @Override + protected void onSetUpInTransaction() throws Exception + { + this.nodeService = (NodeService)this.applicationContext.getBean("nodeService"); + this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService"); + this.personService = (PersonService)this.applicationContext.getBean("personService"); + + AuthenticationComponent authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent"); + authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); + + // Create the store and get the root node + rootNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "spacesStore")); + this.nodeRef = this.nodeService.createNode( + this.rootNodeRef, + ContentModel.ASSOC_CHILDREN, + QName.createQName("{test}testnode"), + ContentModel.TYPE_CONTENT).getChildRef(); + + // Get the executer instance + this.executer = (StartWorkflowActionExecuter)this.applicationContext.getBean(StartWorkflowActionExecuter.NAME); + } + + /** + * Test execution + */ + public void testExecution() + { + // Execute the action + ActionImpl action = new ActionImpl(null, GUID.generate(), StartWorkflowActionExecuter.NAME, null); + action.setParameterValue(StartWorkflowActionExecuter.PARAM_WORKFLOW_NAME, "jbpm://wf:review"); + action.setParameterValue(WorkflowModel.PROP_REVIEW_DUE_DATE.toPrefixString(namespaceService), new Date()); + NodeRef reviewer = personService.getPerson("admin"); + action.setParameterValue(WorkflowModel.ASSOC_REVIEWER.toPrefixString(namespaceService), reviewer); + executer.execute(action, this.nodeRef); + } +} diff --git a/source/java/org/alfresco/repo/workflow/WorkflowComponent.java b/source/java/org/alfresco/repo/workflow/WorkflowComponent.java index 3ebe7fc26d..ea0065cc5c 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowComponent.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowComponent.java @@ -87,6 +87,14 @@ public interface WorkflowComponent */ public WorkflowDefinition getDefinitionById(String workflowDefinitionId); + /** + * Gets a Workflow Definition by unique name + * + * @param workflowName workflow name e.g. jbpm://review + * @return the deployed workflow definition + */ + public WorkflowDefinition getDefinitionByName(String workflowName); + // // Workflow Instance Support diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java index 64ac955e93..bdaac4c483 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java @@ -146,6 +146,16 @@ public class WorkflowServiceImpl implements WorkflowService return component.getDefinitionById(workflowDefinitionId); } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.workflow.WorkflowService#getDefinitionByName(java.lang.String) + */ + public WorkflowDefinition getDefinitionByName(String workflowName) + { + String engineId = BPMEngineRegistry.getEngineId(workflowName); + WorkflowComponent component = getWorkflowComponent(engineId); + return component.getDefinitionByName(workflowName); + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.workflow.WorkflowService#startWorkflow(java.lang.String, java.util.Map) */ diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java index 1fe09531f4..fa7d4af6e1 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java @@ -312,6 +312,30 @@ public class JBPMEngine extends BPMEngine throw new UnsupportedOperationException(); } + /* (non-Javadoc) + * @see org.alfresco.repo.workflow.WorkflowComponent#getDefinitionByName(java.lang.String) + */ + public WorkflowDefinition getDefinitionByName(final String workflowName) + { + try + { + return (WorkflowDefinition)jbpmTemplate.execute(new JbpmCallback() + { + @SuppressWarnings("synthetic-access") + public Object doInJbpm(JbpmContext context) + { + GraphSession graphSession = context.getGraphSession(); + ProcessDefinition processDef = graphSession.findLatestProcessDefinition(createLocalId(workflowName)); + return createWorkflowDefinition(processDef); + } + }); + } + catch(JbpmException e) + { + throw new WorkflowException("Failed to retrieve workflow definition '" + workflowName + "'", e); + } + } + // // Workflow Instance Management... diff --git a/source/java/org/alfresco/repo/workflow/jbpm/NodeListConverterTest.java b/source/java/org/alfresco/repo/workflow/jbpm/NodeListConverterTest.java new file mode 100644 index 0000000000..52c478ceb4 --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/jbpm/NodeListConverterTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.workflow.jbpm; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.workflow.BPMEngineRegistry; +import org.alfresco.repo.workflow.TaskComponent; +import org.alfresco.repo.workflow.WorkflowComponent; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowDeployment; +import org.alfresco.service.cmr.workflow.WorkflowPath; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.BaseSpringTest; +import org.springframework.core.io.ClassPathResource; + + +/** + * JBPM Engine Tests + * + * @author davidc + */ +public class NodeListConverterTest extends BaseSpringTest +{ + AuthenticationComponent authenticationComponent; + PersonService personService; + WorkflowComponent workflowComponent; + TaskComponent taskComponent; + WorkflowDefinition testWorkflowDef; + NodeRef testNodeRef; + + private static String taskId = null; + + + @Override + protected void onSetUpInTransaction() throws Exception + { + personService = (PersonService)applicationContext.getBean("personService"); + BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry"); + workflowComponent = registry.getWorkflowComponent("jbpm"); + taskComponent = registry.getTaskComponent("jbpm"); + + // deploy latest review and approve process definition + ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml"); + WorkflowDeployment deployment = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML); + testWorkflowDef = deployment.definition; + assertNotNull(testWorkflowDef); + + // run as system + authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent"); + authenticationComponent.setSystemUserAsCurrentUser(); + + // get valid node ref + NodeService nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName()); + testNodeRef = nodeService.getRootNode(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "spacesStore")); + } + + + public void testStep1Start() + { + Map params = new HashMap(); + params.put(WorkflowModel.ASSOC_PACKAGE, testNodeRef); + Date reviewDueDate = new Date(); + params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewDueDate"), reviewDueDate); + NodeRef reviewer = personService.getPerson("admin"); + params.put(QName.createQName("http://www.alfresco.org/model/workflow/1.0", "reviewer"), reviewer); + + WorkflowPath path = workflowComponent.startWorkflow(testWorkflowDef.id, params); + assertNotNull(path); + List tasks1 = workflowComponent.getTasksForWorkflowPath(path.id); + assertNotNull(tasks1); + assertEquals(1, tasks1.size()); + + setComplete(); + taskId = tasks1.get(0).id; + } + + + public void testSetNodeRefList() + { + List nodeRefs = new ArrayList(); + nodeRefs.add(testNodeRef); + nodeRefs.add(testNodeRef); + Map params = new HashMap(); + params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs); + + WorkflowTask task = taskComponent.getTaskById(taskId); + assertNull(task.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)); + + WorkflowTask updatedTask = taskComponent.updateTask(taskId, params, null, null); + assertNotNull(updatedTask); + assertTrue(updatedTask.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS)); + assertEquals(2, ((List)updatedTask.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size()); + + setComplete(); + } + + + public void testUpdateNodeRefList() + { + List nodeRefs = new ArrayList(); +// nodeRefs.add(testNodeRef); + Map params = new HashMap(); + params.put(WorkflowModel.PROP_COMPLETED_ITEMS, (Serializable)nodeRefs); + +// WorkflowTask task = taskComponent.getTaskById(taskId); +// assertNotNull(task); +// assertTrue(task.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS)); +// assertEquals(2, ((List)task.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size()); + + WorkflowTask updatedTask = taskComponent.updateTask(taskId, params, null, null); + assertNotNull(updatedTask); + assertTrue(updatedTask.properties.containsKey(WorkflowModel.PROP_COMPLETED_ITEMS)); + assertEquals(0, ((List)updatedTask.properties.get(WorkflowModel.PROP_COMPLETED_ITEMS)).size()); + + setComplete(); + } + +} diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java index fd3d55165d..fe46a1c143 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java @@ -95,7 +95,15 @@ public interface WorkflowService * @return the deployed workflow definition */ public WorkflowDefinition getDefinitionById(String workflowDefinitionId); - + + /** + * Gets a Workflow Definition by unique name + * + * @param workflowName workflow name e.g. jbpm://review + * @return the deployed workflow definition + */ + public WorkflowDefinition getDefinitionByName(String workflowName); + // // Workflow Instance Management