From 17a40c3e51187af306155af048d744a529bcd0fd Mon Sep 17 00:00:00 2001 From: David Caruana Date: Wed, 9 Aug 2006 23:37:06 +0000 Subject: [PATCH] Workflow Checkpoint: - Process deploy/isDeployed/undeploy implemented in Workflow Service - Servlet implemented to support jBPM Process Designer deployment (using above service) : mapped to /alfresco/jbpm/deployprocess URL - Workflow deployer bootstrap bean (for once- only loading of process definitions at bootstrap) - Initial cut of Review & Approve process definition & Task definitions (bootstrapped) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3477 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/bootstrap-context.xml | 14 ++ config/alfresco/model/workflowModel.xml | 59 ++++++ config/alfresco/workflow-context.xml | 21 +- .../alfresco/repo/content/MimetypeMap.java | 1 + .../workflow/WorkflowDefinitionComponent.java | 15 +- .../repo/workflow/WorkflowDeployer.java | 194 ++++++++++++++++++ .../repo/workflow/WorkflowServiceImpl.java | 28 ++- .../repo/workflow/jbpm/JBPMEngine.java | 150 +++++++++++++- .../repo/workflow/jbpm/JBPMEngineTest.java | 33 ++- .../review_and_approve_processdefinition.xml | 43 ++++ .../workflow/jbpm/test_processdefinition.xml | 4 +- .../cmr/workflow/WorkflowDefinition.java | 5 +- .../service/cmr/workflow/WorkflowService.java | 24 +++ 13 files changed, 552 insertions(+), 39 deletions(-) create mode 100644 config/alfresco/model/workflowModel.xml create mode 100644 source/java/org/alfresco/repo/workflow/WorkflowDeployer.java create mode 100644 source/java/org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index a1b78152ca..142ec70343 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -120,6 +120,20 @@ + + + + + + + jbpm + org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml + text/xml + + + + + diff --git a/config/alfresco/model/workflowModel.xml b/config/alfresco/model/workflowModel.xml new file mode 100644 index 0000000000..22f27518cc --- /dev/null +++ b/config/alfresco/model/workflowModel.xml @@ -0,0 +1,59 @@ + + + + + Content-oriented Workflows Model + Alfresco + 0.1 + + + + + + + + + + + + + + + + + + + Submit Review Task + bpm:workflowTask + + + + + Review Due Date + d:date + + + + + + + + Reviewers + + false + false + + + cm:person + true + false + + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml index 4ce9da7ac3..9f7ce0a272 100644 --- a/config/alfresco/workflow-context.xml +++ b/config/alfresco/workflow-context.xml @@ -4,16 +4,23 @@ - + alfresco/model/bpmModel.xml + alfresco/model/workflowModel.xml + + + + + + @@ -41,11 +48,6 @@ - - - - - @@ -57,11 +59,8 @@ + + - - - - - diff --git a/source/java/org/alfresco/repo/content/MimetypeMap.java b/source/java/org/alfresco/repo/content/MimetypeMap.java index 08b9d49f24..272c1cb89d 100644 --- a/source/java/org/alfresco/repo/content/MimetypeMap.java +++ b/source/java/org/alfresco/repo/content/MimetypeMap.java @@ -57,6 +57,7 @@ public class MimetypeMap implements MimetypeService public static final String MIMETYPE_IMAGE_JPEG = "image/jpeg"; public static final String MIMETYPE_IMAGE_RGB = "image/x-rgb"; public static final String MIMETYPE_JAVASCRIPT = "application/x-javascript"; + public static final String MIMETYPE_ZIP = "application/zip"; // Open Document public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text"; public static final String MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE = "application/vnd.oasis.opendocument.text-template"; diff --git a/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java b/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java index 5fd9ef849b..db0530f7f1 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java @@ -34,10 +34,23 @@ public interface WorkflowDefinitionComponent * Deploy a Workflow Definition * * @param workflowDefinition the content object containing the definition + * @param mimetype (optional) the mime type of the workflow definition * @return workflow definition */ - public WorkflowDefinition deployDefinition(InputStream workflowDefinition); + public WorkflowDefinition deployDefinition(InputStream workflowDefinition, String mimetype); + /** + * Is the specified Workflow Definition already deployed? + * + * Note: the notion of "already deployed" may differ between bpm engines. For example, + * different versions of the same process may be considered equal. + * + * @param workflowDefinition the definition to check + * @param mimetype the mimetype of the definition + * @return true => already deployed + */ + public boolean isDefinitionDeployed(InputStream workflowDefinition, String mimetype); + /** * Undeploy an exisiting Workflow Definition * diff --git a/source/java/org/alfresco/repo/workflow/WorkflowDeployer.java b/source/java/org/alfresco/repo/workflow/WorkflowDeployer.java new file mode 100644 index 0000000000..faf01522ba --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/WorkflowDeployer.java @@ -0,0 +1,194 @@ +/* + * 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.InputStream; +import java.util.List; +import java.util.Properties; + +import javax.transaction.UserTransaction; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.service.cmr.view.ImporterException; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowException; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.io.ClassPathResource; + + +/** + * Alfresco bootstrap Process deployment. + * + * @author davidc + */ +public class WorkflowDeployer implements ApplicationListener +{ + // Logging support + private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow"); + + // Workflow Definition Properties (used in setWorkflowDefinitions) + public static final String ENGINE_ID = "engineId"; + public static final String LOCATION = "location"; + public static final String MIMETYPE = "mimetype"; + + // Dependencies + private TransactionService transactionService; + private WorkflowService workflowService; + private AuthenticationComponent authenticationComponent; + private List workflowDefinitions; + + + /** + * Sets the Transaction Service + * + * @param userTransaction the transaction service + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + /** + * Sets the namespace service + * + * @param namespaceService the namespace service + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /** + * Set the authentication component + * + * @param authenticationComponent + */ + public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) + { + this.authenticationComponent = authenticationComponent; + } + + /** + * Sets the Workflow Definitions + * + * @param workflowDefinitions + */ + public void setWorkflowDefinitions(List workflowDefinitions) + { + this.workflowDefinitions = workflowDefinitions; + } + + /** + * Deploy the Workflow Definitions + */ + public void deploy() + { + if (transactionService == null) + { + throw new ImporterException("Transaction Service must be provided"); + } + if (authenticationComponent == null) + { + throw new ImporterException("Authentication Component must be provided"); + } + if (workflowService == null) + { + throw new ImporterException("Workflow Service must be provided"); + } + + UserTransaction userTransaction = transactionService.getUserTransaction(); + authenticationComponent.setSystemUserAsCurrentUser(); + + try + { + userTransaction.begin(); + + // bootstrap the workflow definitions + if (workflowDefinitions != null) + { + for (Properties workflowDefinition : workflowDefinitions) + { + // retrieve workflow specification + String engineId = workflowDefinition.getProperty(ENGINE_ID); + if (engineId == null || engineId.length() == 0) + { + throw new WorkflowException("Workflow Engine Id must be provided"); + } + String location = workflowDefinition.getProperty(LOCATION); + if (location == null || location.length() == 0) + { + throw new WorkflowException("Workflow definition location must be provided"); + } + String mimetype = workflowDefinition.getProperty(MIMETYPE); + + // retrieve input stream on workflow definition + ClassPathResource workflowResource = new ClassPathResource(location); + + // deploy workflow definition + if (workflowService.isDefinitionDeployed(engineId, workflowResource.getInputStream(), mimetype)) + { + if (logger.isDebugEnabled()) + { + logger.debug("Workflow deployer: Definition '" + location + "' already deployed"); + } + } + else + { + WorkflowDefinition def = workflowService.deployDefinition(engineId, workflowResource.getInputStream(), mimetype); + if (logger.isInfoEnabled()) + { + logger.info("Workflow deployer: Deployed process definition '" + def.name + "' (version " + def.version + ") from '" + location + "'"); + } + } + } + } + + userTransaction.commit(); + } + catch(Throwable e) + { + // rollback the transaction + try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {} + try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {} + throw new AlfrescoRuntimeException("Workflow deployment failed", e); + } + finally + { + authenticationComponent.clearCurrentSecurityContext(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) + */ + public void onApplicationEvent(ApplicationEvent event) + { + if (event instanceof ContextRefreshedEvent) + { + deploy(); + } + } + +} diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java index c7b10a776c..406db91cb7 100644 --- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java +++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java @@ -16,6 +16,7 @@ */ package org.alfresco.repo.workflow; +import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -55,6 +56,24 @@ public class WorkflowServiceImpl implements WorkflowService } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(java.lang.String, java.io.InputStream, java.lang.String) + */ + public WorkflowDefinition deployDefinition(String engineId, InputStream workflowDefinition, String mimetype) + { + WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId); + return component.deployDefinition(workflowDefinition, mimetype); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.workflow.WorkflowService#isDefinitionDeployed(java.lang.String, java.io.InputStream, java.lang.String) + */ + public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype) + { + WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId); + return component.isDefinitionDeployed(workflowDefinition, mimetype); + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.workflow.WorkflowService#deployDefinition(org.alfresco.service.cmr.repository.NodeRef) */ @@ -67,10 +86,11 @@ public class WorkflowServiceImpl implements WorkflowService /* (non-Javadoc) * @see org.alfresco.service.cmr.workflow.WorkflowService#undeployDefinition(java.lang.String) */ - public void undeployDefinition(String processDefinitionId) + public void undeployDefinition(String workflowDefinitionId) { - // TODO - throw new UnsupportedOperationException(); + String engineId = BPMEngineRegistry.getEngineId(workflowDefinitionId); + WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId); + component.undeployDefinition(workflowDefinitionId); } /* (non-Javadoc) @@ -275,5 +295,5 @@ public class WorkflowServiceImpl implements WorkflowService } return component; } - + } diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java index d7d50aedb3..b41087abd7 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java @@ -16,6 +16,7 @@ */ package org.alfresco.repo.workflow.jbpm; +import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; @@ -25,8 +26,10 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; +import java.util.zip.ZipInputStream; import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.workflow.BPMEngine; import org.alfresco.repo.workflow.TaskComponent; @@ -144,19 +147,90 @@ public class JBPMEngine extends BPMEngine /* (non-Javadoc) * @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#deployDefinition(java.io.InputStream) */ - public WorkflowDefinition deployDefinition(InputStream workflowDefinition) + public WorkflowDefinition deployDefinition(final InputStream workflowDefinition, final String mimetype) { - // TODO - throw new UnsupportedOperationException(); + try + { + return (WorkflowDefinition)jbpmTemplate.execute(new JbpmCallback() + { + public Object doInJbpm(JbpmContext context) + { + // construct process definition + ProcessDefinition def = createProcessDefinition(workflowDefinition, mimetype); + + // deploy the parsed definition + context.deployProcessDefinition(def); + + // return deployed definition + WorkflowDefinition workflowDef = createWorkflowDefinition(def); + return workflowDef; + } + }); + } + catch(JbpmException e) + { + throw new WorkflowException("Failed to deploy workflow definition", e); + } } + + /* (non-Javadoc) + * @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#isDefinitionDeployed(java.io.InputStream, java.lang.String) + */ + public boolean isDefinitionDeployed(final InputStream workflowDefinition, final String mimetype) + { + try + { + return (Boolean) jbpmTemplate.execute(new JbpmCallback() + { + public Boolean doInJbpm(JbpmContext context) + { + // create process definition from input stream + ProcessDefinition processDefinition = createProcessDefinition(workflowDefinition, mimetype); + + // retrieve process definition from Alfresco Repository + GraphSession graphSession = context.getGraphSession(); + ProcessDefinition existingDefinition = graphSession.findLatestProcessDefinition(processDefinition.getName()); + return (existingDefinition == null) ? false : true; + } + }); + } + catch(JbpmException e) + { + throw new WorkflowException("Failed to determine if workflow definition is already deployed", e); + } + } + /* (non-Javadoc) * @see org.alfresco.repo.workflow.WorkflowDefinitionComponent#undeployDefinition(java.lang.String) */ - public void undeployDefinition(String workflowDefinitionId) + public void undeployDefinition(final String workflowDefinitionId) { - // TODO - throw new UnsupportedOperationException(); + try + { + jbpmTemplate.execute(new JbpmCallback() + { + public Object doInJbpm(JbpmContext context) + { + // retrieve process definition + GraphSession graphSession = context.getGraphSession(); + ProcessDefinition processDefinition = graphSession.loadProcessDefinition(getJbpmId(workflowDefinitionId)); + // NOTE: if not found, should throw an exception + + // undeploy + // NOTE: jBPM deletes all "in-flight" processes too + // TODO: Determine if there's a safer undeploy we can expose via the WorkflowService contract + graphSession.deleteProcessDefinition(processDefinition); + + // we're done + return null; + } + }); + } + catch(JbpmException e) + { + throw new WorkflowException("Failed to deploy workflow definition", e); + } } /* (non-Javadoc) @@ -674,6 +748,58 @@ public class JBPMEngine extends BPMEngine // Helpers... // + /** + * Construct a Process Definition from the provided Process Definition stream + * + * @param workflowDefinition stream to create process definition from + * @param mimetype mimetype of stream + * @return process definition + */ + protected ProcessDefinition createProcessDefinition(InputStream definitionStream, String mimetype) + { + String actualMimetype = (mimetype == null) ? MimetypeMap.MIMETYPE_ZIP : mimetype; + ProcessDefinition def = null; + + // parse process definition from jBPM process archive file + + if (actualMimetype.equals(MimetypeMap.MIMETYPE_ZIP)) + { + ZipInputStream zipInputStream = null; + try + { + zipInputStream = new ZipInputStream(definitionStream); + def = ProcessDefinition.parseParZipInputStream(zipInputStream); + } + catch(Exception e) + { + throw new JbpmException("Failed to parse process definition from jBPM zip archive stream", e); + } + finally + { + if (zipInputStream != null) + { + try { zipInputStream.close(); } catch(IOException e) {}; + } + } + } + + // parse process definition from jBPM xml file + + else if (actualMimetype.equals(MimetypeMap.MIMETYPE_XML)) + { + try + { + def = ProcessDefinition.parseXmlInputStream(definitionStream); + } + catch(Exception e) + { + throw new JbpmException("Failed to parse process definition from jBPM xml stream", e); + } + } + + return def; + } + /** * Gets the Task definition of the specified Task * @@ -1013,11 +1139,14 @@ public class JBPMEngine extends BPMEngine // TODO: Is there a formal way of determing if task node? workflowNode.isTaskNode = workflowNode.type.equals("TaskNode"); List transitions = node.getLeavingTransitions(); - workflowNode.transitions = new String[transitions.size()]; - int i = 0; - for (Transition transition : (List)transitions) + workflowNode.transitions = new String[(transitions == null) ? 0 : transitions.size()]; + if (transitions != null) { - workflowNode.transitions[i++] = transition.getName(); + int i = 0; + for (Transition transition : (List)transitions) + { + workflowNode.transitions[i++] = transition.getName(); + } } return workflowNode; } @@ -1047,6 +1176,7 @@ public class JBPMEngine extends BPMEngine { WorkflowDefinition workflowDef = new WorkflowDefinition(); workflowDef.id = createGlobalId(new Long(definition.getId()).toString()); + workflowDef.version = new Integer(definition.getVersion()).toString(); workflowDef.name = definition.getName(); Task startTask = definition.getTaskMgmtDefinition().getStartTask(); if (startTask != null) diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java index 0f9d53b058..dcb4d35d35 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java +++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.workflow.BPMEngineRegistry; import org.alfresco.repo.workflow.TaskComponent; import org.alfresco.repo.workflow.WorkflowComponent; @@ -39,6 +40,7 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.BaseSpringTest; +import org.springframework.core.io.ClassPathResource; /** @@ -51,6 +53,7 @@ public class JBPMEngineTest extends BaseSpringTest WorkflowDefinitionComponent workflowDefinitionComponent; WorkflowComponent workflowComponent; TaskComponent taskComponent; + WorkflowDefinition testWorkflowDef; //@Override @@ -60,6 +63,15 @@ public class JBPMEngineTest extends BaseSpringTest workflowDefinitionComponent = registry.getWorkflowDefinitionComponent("jbpm"); workflowComponent = registry.getWorkflowComponent("jbpm"); taskComponent = registry.getTaskComponent("jbpm"); + + // deploy test process definition + ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml"); + assertFalse(workflowDefinitionComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML)); + testWorkflowDef = workflowDefinitionComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML); + assertNotNull(testWorkflowDef); + assertEquals("Test", testWorkflowDef.name); + assertEquals("1", testWorkflowDef.version); + assertTrue(workflowDefinitionComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML)); } @@ -71,6 +83,16 @@ public class JBPMEngineTest extends BaseSpringTest } + public void testDeployWorkflow() throws Exception + { + ClassPathResource processDef = new ClassPathResource("org/alfresco/repo/workflow/jbpm/test_processdefinition.xml"); + testWorkflowDef = workflowDefinitionComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML); + assertNotNull(testWorkflowDef); + assertEquals("Test", testWorkflowDef.name); + assertEquals("2", testWorkflowDef.version); + } + + public void testStartWorkflow() { try @@ -321,16 +343,7 @@ public class JBPMEngineTest extends BaseSpringTest */ private WorkflowDefinition getTestDefinition() { - List workflowDefs = workflowDefinitionComponent.getDefinitions(); - for (WorkflowDefinition workflowDef : workflowDefs) - { - if (workflowDef.name.equals("Review and Approve")) - { - return workflowDef; - } - } - fail("Test Workflow Definition not found"); - return null; + return testWorkflowDef; } } diff --git a/source/java/org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml b/source/java/org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml new file mode 100644 index 0000000000..1b242cb5ba --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/jbpm/review_and_approve_processdefinition.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml b/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml index 1b242cb5ba..b4ad00f47f 100644 --- a/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml +++ b/source/java/org/alfresco/repo/workflow/jbpm/test_processdefinition.xml @@ -1,9 +1,9 @@ - + - + diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowDefinition.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowDefinition.java index d427ecf63f..04651de5a4 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowDefinition.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowDefinition.java @@ -27,6 +27,9 @@ public class WorkflowDefinition /** Workflow Definition unique id */ public String id; + /** Workflow Definition version */ + public String version; + /** Workflow Definition name */ public String name; @@ -39,6 +42,6 @@ public class WorkflowDefinition */ public String toString() { - return "WorkflowDefinition[id=" + id + ",name=" + name + ",startTask=" + startTaskDefinition.toString() + "]"; + return "WorkflowDefinition[id=" + id + ",version=" + version + ",name=" + name + ",startTask=" + startTaskDefinition.toString() + "]"; } } diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java index fe573799b0..40ac0fb6ce 100644 --- a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java +++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java @@ -16,6 +16,7 @@ */ package org.alfresco.service.cmr.workflow; +import java.io.InputStream; import java.io.Serializable; import java.util.List; import java.util.Map; @@ -37,6 +38,29 @@ public interface WorkflowService // Workflow Definition Management // + /** + * Deploy a Workflow Definition to the Alfresco Repository + * + * @param engineId the bpm engine id + * @param workflowDefinition the workflow definition + * @param overwrite true => redeploy, if process definition already exists + * @return mimetype the mimetype of the workflow definition + */ + public WorkflowDefinition deployDefinition(String engineId, InputStream workflowDefinition, String mimetype); + + /** + * Is the specified Workflow Definition already deployed? + * + * Note: the notion of "already deployed" may differ between bpm engines. For example, + * different versions of the same process may be considered equal. + * + * @param engineId the bpm engine id + * @param workflowDefinition the definition to check + * @param mimetype the mimetype of the definition + * @return true => already deployed + */ + public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype); + /** * Deploy a Workflow Definition to the Alfresco Repository *