diff --git a/config/alfresco/bootstrap/system.xml b/config/alfresco/bootstrap/system.xml
index ea825f418e..9ac123b6ad 100644
--- a/config/alfresco/bootstrap/system.xml
+++ b/config/alfresco/bootstrap/system.xml
@@ -42,6 +42,7 @@
+
diff --git a/config/alfresco/import-export-context.xml b/config/alfresco/import-export-context.xml
index d2b6b474d7..e5b10d42ee 100644
--- a/config/alfresco/import-export-context.xml
+++ b/config/alfresco/import-export-context.xml
@@ -255,6 +255,7 @@
${spaces.guest_home.childname}
${system.system_container.childname}
${system.people_container.childname}
+ ${system.workflow_container.childname}
${spaces.dictionary.childname}
${spaces.templates.childname}
${spaces.templates.content.childname}
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 1ee0606d81..402fba27b9 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -74,4 +74,7 @@ patch.topLevelGroupParentChildAssociationTypePatch.err.sys_path_not_found=Requir
patch.topLevelGroupParentChildAssociationTypePatch.err.auth_path_not_found=Required authority path not found: {0}
patch.actionRuleDecouplingPatch.description=Migrate existing rules to the updated model where rules are decoupled from actions.
-patch.actionRuleDecouplingPatch.result=Updated {0} rules.
\ No newline at end of file
+patch.actionRuleDecouplingPatch.result=Updated {0} rules.
+
+patch.systemWorkflowFolder.description=Ensures the existence of the system workflow container.
+patch.systemWorkflowFolder.result.created=Created system workflow container {0}.
\ No newline at end of file
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 9cf5fd4909..5674a986cf 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -379,4 +379,14 @@
15
+
+ patch.systemWorkflowFolderPatch
+ patch.systemWorkflowFolder.description
+ 0
+ 15
+ 16
+
+
+
+
diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties
index 95752d6830..bcfedefc8a 100644
--- a/config/alfresco/repository.properties
+++ b/config/alfresco/repository.properties
@@ -105,6 +105,10 @@ spaces.scripts.childname=app:scripts
system.system_container.childname=sys:system
system.people_container.childname=sys:people
+# Folders for storing workflow related info
+
+system.workflow_container.childname=sys:workflow
+
# Are user names case sensitive?
# ==============================
#
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index 9069f83ce6..d309203a47 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
-version.schema=15
+version.schema=16
diff --git a/config/alfresco/workflow-context.xml b/config/alfresco/workflow-context.xml
index 1d3cd3e1a0..f6f8daf38f 100644
--- a/config/alfresco/workflow-context.xml
+++ b/config/alfresco/workflow-context.xml
@@ -28,6 +28,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/SystemWorkflowFolderPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/SystemWorkflowFolderPatch.java
new file mode 100644
index 0000000000..65d0c96ead
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/SystemWorkflowFolderPatch.java
@@ -0,0 +1,51 @@
+/*
+ * 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.admin.patch.impl;
+
+import org.alfresco.i18n.I18NUtil;
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.repo.workflow.WorkflowPackageImpl;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+
+/**
+ * Ensures the system folder for Workflows is created.
+ *
+ * @author davidc
+ */
+public class SystemWorkflowFolderPatch extends AbstractPatch
+{
+ private static final String MSG_CREATED = "patch.systemWorkflowFolder.result.created";
+
+ private WorkflowPackageImpl workflowPackageImpl;
+
+ public void setWorkflowPackageImpl(WorkflowPackageImpl workflowPackageImpl)
+ {
+ this.workflowPackageImpl = workflowPackageImpl;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.admin.patch.AbstractPatch#applyInternal()
+ */
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ NodeRef systemContainer = workflowPackageImpl.createSystemWorkflowContainer();
+ return I18NUtil.getMessage(MSG_CREATED, systemContainer);
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/workflow/BPMEngine.java b/source/java/org/alfresco/repo/workflow/BPMEngine.java
index 7083475f0c..82cae295b3 100644
--- a/source/java/org/alfresco/repo/workflow/BPMEngine.java
+++ b/source/java/org/alfresco/repo/workflow/BPMEngine.java
@@ -62,10 +62,6 @@ public class BPMEngine implements InitializingBean
throw new WorkflowException("Engine Id not specified");
}
- if (this instanceof WorkflowDefinitionComponent)
- {
- registry.registerWorkflowDefinitionComponent(engineId, (WorkflowDefinitionComponent)this);
- }
if (this instanceof WorkflowComponent)
{
registry.registerWorkflowComponent(engineId, (WorkflowComponent)this);
diff --git a/source/java/org/alfresco/repo/workflow/BPMEngineRegistry.java b/source/java/org/alfresco/repo/workflow/BPMEngineRegistry.java
index c2024b0a6d..3c37f98378 100644
--- a/source/java/org/alfresco/repo/workflow/BPMEngineRegistry.java
+++ b/source/java/org/alfresco/repo/workflow/BPMEngineRegistry.java
@@ -30,7 +30,6 @@ import org.apache.commons.logging.LogFactory;
* Responsible for managing the list of registered BPM Engines for the
* following components:
*
- * - Workflow Definition Component
* - Workflow Component
* - Task Component
*
@@ -44,7 +43,6 @@ public class BPMEngineRegistry
/** Logging support */
private static Log logger = LogFactory.getLog("org.alfresco.repo.workflow");
- private Map workflowDefinitionComponents;
private Map workflowComponents;
private Map taskComponents;
@@ -54,50 +52,10 @@ public class BPMEngineRegistry
*/
public BPMEngineRegistry()
{
- workflowDefinitionComponents = new HashMap();
workflowComponents = new HashMap();
taskComponents = new HashMap();
}
- /**
- * Register a BPM Engine Workflow Definition Component
- *
- * @param engineId engine id
- * @param engine implementing engine
- */
- public void registerWorkflowDefinitionComponent(String engineId, WorkflowDefinitionComponent engine)
- {
- if (workflowDefinitionComponents.containsKey(engineId))
- {
- throw new WorkflowException("Workflow Definition Component already registered for engine id '" + engineId + "'");
- }
- workflowDefinitionComponents.put(engineId, engine);
-
- if (logger.isInfoEnabled())
- logger.info("Registered Workflow Definition Component '" + engineId + "' (" + engine.getClass() + ")");
- }
-
- /**
- * Gets all registered Workflow Definition Components
- *
- * @return array of engine ids
- */
- public String[] getWorkflowDefinitionComponents()
- {
- return workflowDefinitionComponents.keySet().toArray(new String[workflowDefinitionComponents.keySet().size()]);
- }
-
- /**
- * Gets a specific BPM Engine Workflow Definition Component
- *
- * @param engineId engine id
- * @return the Workflow Definition Component
- */
- public WorkflowDefinitionComponent getWorkflowDefinitionComponent(String engineId)
- {
- return workflowDefinitionComponents.get(engineId);
- }
-
/**
* Register a BPM Engine Workflow Component
*
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowComponent.java b/source/java/org/alfresco/repo/workflow/WorkflowComponent.java
index a0f742e866..c397173f5d 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowComponent.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowComponent.java
@@ -16,10 +16,12 @@
*/
package org.alfresco.repo.workflow;
+import java.io.InputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
+import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowTask;
@@ -34,6 +36,62 @@ import org.alfresco.service.namespace.QName;
public interface WorkflowComponent
{
+ //
+ // Workflow Definition Support
+ //
+
+
+ /**
+ * 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, 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
+ *
+ * TODO: Determine behaviour when "in-flight" workflow instances exist
+ *
+ * @param workflowDefinitionId the id of the definition to undeploy
+ */
+ public void undeployDefinition(String workflowDefinitionId);
+
+ /**
+ * Gets all deployed Workflow Definitions
+ *
+ * @return the deployed workflow definitions
+ */
+ public List getDefinitions();
+
+ /**
+ * Gets a Workflow Definition by unique Id
+ *
+ * @param workflowDefinitionId the workflow definition id
+ * @return the deployed workflow definition
+ */
+ public WorkflowDefinition getDefinitionById(String workflowDefinitionId);
+
+
+ //
+ // Workflow Instance Support
+ //
+
+
/**
* Start a Workflow Instance
*
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java b/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java
deleted file mode 100644
index db0530f7f1..0000000000
--- a/source/java/org/alfresco/repo/workflow/WorkflowDefinitionComponent.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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 org.alfresco.service.cmr.workflow.WorkflowDefinition;
-
-
-/**
- * SPI to be implemented by a BPM Engine that provides Workflow Definition management.
- *
- * @author davidc
- */
-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, 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
- *
- * TODO: Determine behaviour when "in-flight" workflow instances exist
- *
- * @param workflowDefinitionId the id of the definition to undeploy
- */
- public void undeployDefinition(String workflowDefinitionId);
-
- /**
- * Gets all deployed Workflow Definitions
- *
- * @return the deployed workflow definitions
- */
- public List getDefinitions();
-
- /**
- * Gets a Workflow Definition by unique Id
- *
- * @param workflowDefinitionId the workflow definition id
- * @return the deployed workflow definition
- */
- public WorkflowDefinition getDefinitionById(String workflowDefinitionId);
-
-}
-
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowModel.java b/source/java/org/alfresco/repo/workflow/WorkflowModel.java
index 1b3b5de626..2e082cee7f 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowModel.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowModel.java
@@ -41,5 +41,8 @@ public interface WorkflowModel
static final QName TYPE_WORKFLOW_TASK = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowTask");
static final QName PROP_CONTEXT = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "context");
static final QName ASSOC_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "package");
+
+ // workflow package
+ static final QName ASPECT_WORKFLOW_PACKAGE = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "workflowPackage");
}
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowPackageComponent.java b/source/java/org/alfresco/repo/workflow/WorkflowPackageComponent.java
new file mode 100644
index 0000000000..8a4675b3d2
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/WorkflowPackageComponent.java
@@ -0,0 +1,43 @@
+/*
+ * 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 org.alfresco.service.cmr.repository.NodeRef;
+
+
+/**
+ * Contract for managing Workflow Packages. A package is a container
+ * of Content that's routed through a Workflow.
+ *
+ * @author davidc
+ */
+public interface WorkflowPackageComponent
+{
+
+ /**
+ * Create a Workflow Package (a container of content to route through the Workflow).
+ *
+ * If an existing container is supplied, it's supplemented with the workflow package aspect.
+ *
+ * @param container (optional) a pre-created container (e.g. folder, versioned folder or layered folder)
+ * @return the workflow package
+ */
+ public NodeRef createPackage(NodeRef container);
+
+ // TODO: Support for finding packages via meta-data of WorkflowPackage aspect
+
+}
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowPackageImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowPackageImpl.java
new file mode 100644
index 0000000000..3f15a29649
--- /dev/null
+++ b/source/java/org/alfresco/repo/workflow/WorkflowPackageImpl.java
@@ -0,0 +1,210 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.importer.ImporterBootstrap;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.model.FileInfo;
+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.search.SearchService;
+import org.alfresco.service.cmr.workflow.WorkflowException;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.GUID;
+
+
+/**
+ * Alfresco implementation of Workflow Package where the package is stored
+ * within the Alfresco Repository.
+ *
+ * @author davidc
+ */
+public class WorkflowPackageImpl implements WorkflowPackageComponent
+{
+ private final static String PACKAGE_FOLDER = "Workflow Packages";
+
+ // service dependencies
+ private ImporterBootstrap bootstrap;
+ private SearchService searchService;
+ private NodeService nodeService;
+ private NamespaceService namespaceService;
+ private FileFolderService fileFolderService;
+ private NodeRef systemWorkflowContainer = null;
+
+
+ /**
+ * @param bootstrap the importer bootstrap for the store to place workflow items into
+ */
+ public void setImporterBootstrap(ImporterBootstrap bootstrap)
+ {
+ this.bootstrap = bootstrap;
+ }
+
+ /**
+ * @param fileFolderService file folder service
+ */
+ public void setFileFolderService(FileFolderService fileFolderService)
+ {
+ this.fileFolderService = fileFolderService;
+ }
+
+ /**
+ * @param searchService search service
+ */
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ /**
+ * @param nodeService node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * @param namespaceService namespace service
+ */
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.workflow.WorkflowPackageComponent#createPackage(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ public NodeRef createPackage(NodeRef container)
+ {
+ // create a container, if one is not specified
+ if (container == null)
+ {
+ // create simple folder in workflow system folder
+ NodeRef system = getSystemWorkflowContainer();
+
+ // TODO: Consider structuring this folder, if number of children becomes an issue
+ List folders = new ArrayList();
+ folders.add(PACKAGE_FOLDER);
+ folders.add(GUID.generate());
+ FileInfo containerFolder = fileFolderService.makeFolders(system, folders, ContentModel.TYPE_FOLDER);
+ container = containerFolder.getNodeRef();
+ }
+
+ // attach workflow package
+ if (nodeService.hasAspect(container, WorkflowModel.ASPECT_WORKFLOW_PACKAGE))
+ {
+ throw new WorkflowException("Container '" + container + "' is already a workflow package.");
+ }
+ nodeService.addAspect(container, WorkflowModel.ASPECT_WORKFLOW_PACKAGE, null);
+
+ // return container
+ return container;
+ }
+
+
+ /**
+ * Gets the system workflow container for storing workflow related items
+ *
+ * @return the system workflow container
+ */
+ private NodeRef getSystemWorkflowContainer()
+ {
+ if (systemWorkflowContainer == null)
+ {
+ NodeRef systemContainer = findSystemContainer();
+ systemWorkflowContainer = findSystemWorkflowContainer(systemContainer);
+ if (systemWorkflowContainer == null)
+ {
+ throw new WorkflowException("Unable to find system workflow folder - does not exist.");
+ }
+ }
+ return systemWorkflowContainer;
+ }
+
+
+ /**
+ * Finds the system workflow container
+ *
+ * @param systemContainer the system container
+ * @return the system workflow container
+ */
+ private NodeRef findSystemWorkflowContainer(NodeRef systemContainer)
+ {
+ String path = bootstrap.getConfiguration().getProperty("system.workflow_container.childname");
+ if (path == null)
+ {
+ throw new WorkflowException("Unable to locate workflow system container - path not specified");
+ }
+ List nodeRefs = searchService.selectNodes(systemContainer, path, null, namespaceService, false);
+ if (nodeRefs != null && nodeRefs.size() > 0)
+ {
+ systemWorkflowContainer = nodeRefs.get(0);
+ }
+ return systemWorkflowContainer;
+ }
+
+
+ /**
+ * Finds the system container
+ *
+ * @return the system container
+ */
+ private NodeRef findSystemContainer()
+ {
+ String path = bootstrap.getConfiguration().getProperty("system.system_container.childname");
+ if (path == null)
+ {
+ throw new WorkflowException("Unable to locate system container - path not specified");
+ }
+ NodeRef root = nodeService.getRootNode(bootstrap.getStoreRef());
+ List nodeRefs = searchService.selectNodes(root, path, null, namespaceService, false);
+ if (nodeRefs == null || nodeRefs.size() == 0)
+ {
+ throw new WorkflowException("Unable to locate system container - path not found");
+ }
+ return nodeRefs.get(0);
+ }
+
+
+ /**
+ * Creates the System Workflow Container
+ *
+ * @return the system workflow container
+ */
+ public NodeRef createSystemWorkflowContainer()
+ {
+ NodeRef systemContainer = findSystemContainer();
+ NodeRef systemWorkflowContainer = findSystemWorkflowContainer(systemContainer);
+ if (systemWorkflowContainer == null)
+ {
+ String name = bootstrap.getConfiguration().getProperty("system.workflow_container.childname");
+ QName qname = QName.createQName(name, namespaceService);
+ ChildAssociationRef childRef = nodeService.createNode(systemContainer, ContentModel.ASSOC_CHILDREN, qname, ContentModel.TYPE_FOLDER);
+ systemWorkflowContainer = childRef.getChildRef();
+ }
+ return systemWorkflowContainer;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
index 2a850519af..770f8b2a0f 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImpl.java
@@ -43,6 +43,7 @@ import org.alfresco.service.namespace.QName;
public class WorkflowServiceImpl implements WorkflowService
{
private BPMEngineRegistry registry;
+ private WorkflowPackageComponent workflowPackageComponent;
/**
@@ -55,13 +56,23 @@ public class WorkflowServiceImpl implements WorkflowService
this.registry = registry;
}
+ /**
+ * Sets the Workflow Package Component
+ *
+ * @param workflowPackage workflow package component
+ */
+ public void setWorkflowPackageComponent(WorkflowPackageComponent workflowPackageComponent)
+ {
+ this.workflowPackageComponent = workflowPackageComponent;
+ }
+
/* (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);
+ WorkflowComponent component = getWorkflowComponent(engineId);
return component.deployDefinition(workflowDefinition, mimetype);
}
@@ -70,7 +81,7 @@ public class WorkflowServiceImpl implements WorkflowService
*/
public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype)
{
- WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
+ WorkflowComponent component = getWorkflowComponent(engineId);
return component.isDefinitionDeployed(workflowDefinition, mimetype);
}
@@ -89,7 +100,7 @@ public class WorkflowServiceImpl implements WorkflowService
public void undeployDefinition(String workflowDefinitionId)
{
String engineId = BPMEngineRegistry.getEngineId(workflowDefinitionId);
- WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
+ WorkflowComponent component = getWorkflowComponent(engineId);
component.undeployDefinition(workflowDefinitionId);
}
@@ -99,10 +110,10 @@ public class WorkflowServiceImpl implements WorkflowService
public List getDefinitions()
{
List definitions = new ArrayList(10);
- String[] ids = registry.getWorkflowDefinitionComponents();
+ String[] ids = registry.getWorkflowComponents();
for (String id: ids)
{
- WorkflowDefinitionComponent component = registry.getWorkflowDefinitionComponent(id);
+ WorkflowComponent component = registry.getWorkflowComponent(id);
definitions.addAll(component.getDefinitions());
}
return Collections.unmodifiableList(definitions);
@@ -114,7 +125,7 @@ public class WorkflowServiceImpl implements WorkflowService
public WorkflowDefinition getDefinitionById(String workflowDefinitionId)
{
String engineId = BPMEngineRegistry.getEngineId(workflowDefinitionId);
- WorkflowDefinitionComponent component = getWorkflowDefinitionComponent(engineId);
+ WorkflowComponent component = getWorkflowComponent(engineId);
return component.getDefinitionById(workflowDefinitionId);
}
@@ -254,25 +265,9 @@ public class WorkflowServiceImpl implements WorkflowService
/* (non-Javadoc)
* @see org.alfresco.service.cmr.workflow.WorkflowService#createPackage(java.lang.String, org.alfresco.service.cmr.repository.NodeRef)
*/
- public NodeRef createPackage(String workflowDefinitionId, NodeRef container)
+ public NodeRef createPackage(NodeRef container)
{
- // TODO
- throw new UnsupportedOperationException();
- }
-
- /**
- * Gets the Workflow Definition Component registered against the specified BPM Engine Id
- *
- * @param engineId engine id
- */
- private WorkflowDefinitionComponent getWorkflowDefinitionComponent(String engineId)
- {
- WorkflowDefinitionComponent component = registry.getWorkflowDefinitionComponent(engineId);
- if (component == null)
- {
- throw new WorkflowException("Workflow Definition Component for engine id '" + engineId + "' is not registered");
- }
- return component;
+ return workflowPackageComponent.createPackage(container);
}
/**
diff --git a/source/java/org/alfresco/repo/workflow/WorkflowServiceImplTest.java b/source/java/org/alfresco/repo/workflow/WorkflowServiceImplTest.java
index c41b546332..8d61c1ee2a 100644
--- a/source/java/org/alfresco/repo/workflow/WorkflowServiceImplTest.java
+++ b/source/java/org/alfresco/repo/workflow/WorkflowServiceImplTest.java
@@ -19,6 +19,8 @@ package org.alfresco.repo.workflow;
import java.util.List;
import org.alfresco.service.ServiceRegistry;
+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.WorkflowPath;
import org.alfresco.service.cmr.workflow.WorkflowService;
@@ -33,11 +35,13 @@ import org.alfresco.util.BaseSpringTest;
public class WorkflowServiceImplTest extends BaseSpringTest
{
WorkflowService workflowService;
+ NodeService nodeService;
//@Override
protected void onSetUpInTransaction() throws Exception
{
workflowService = (WorkflowService)applicationContext.getBean(ServiceRegistry.WORKFLOW_SERVICE.getLocalName());
+ nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
}
public void testGetWorkflowDefinitions()
@@ -60,4 +64,13 @@ public class WorkflowServiceImplTest extends BaseSpringTest
assertNotNull(path.instance);
assertEquals(workflowDef.id, path.instance.definition.id);
}
+
+ public void testWorkflowPackage()
+ {
+ NodeRef nodeRef = workflowService.createPackage(null);
+ assertNotNull(nodeRef);
+ assertTrue(nodeService.hasAspect(nodeRef, WorkflowModel.ASPECT_WORKFLOW_PACKAGE));
+ setComplete();
+ }
+
}
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
index 5b713ffb03..be48931089 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngine.java
@@ -34,7 +34,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.workflow.BPMEngine;
import org.alfresco.repo.workflow.TaskComponent;
import org.alfresco.repo.workflow.WorkflowComponent;
-import org.alfresco.repo.workflow.WorkflowDefinitionComponent;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
@@ -55,6 +54,8 @@ import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.hibernate.Query;
+import org.hibernate.Session;
import org.hibernate.proxy.HibernateProxy;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
@@ -81,7 +82,7 @@ import org.springmodules.workflow.jbpm31.JbpmTemplate;
* @author davidc
*/
public class JBPMEngine extends BPMEngine
- implements WorkflowDefinitionComponent, WorkflowComponent, TaskComponent
+ implements WorkflowComponent, TaskComponent
{
// Implementation dependencies
protected DictionaryService dictionaryService;
@@ -91,6 +92,16 @@ public class JBPMEngine extends BPMEngine
protected PersonService personService;
private JbpmTemplate jbpmTemplate;
+ // Note: jBPM query which is not provided out-of-the-box
+ // TODO: Check jBPM 3.2 and get this implemented in jBPM
+ private final static String COMPLETED_TASKS_QUERY =
+ "select ti " +
+ "from org.jbpm.taskmgmt.exe.TaskInstance as ti " +
+ "where ti.actorId = :actorId " +
+ "and ti.isOpen = false " +
+ "and ti.end is not null";
+
+
/**
* Sets the JBPM Template used for accessing JBoss JBPM in the correct context
*
@@ -528,27 +539,61 @@ public class JBPMEngine extends BPMEngine
public List doInJbpm(JbpmContext context)
{
// retrieve tasks assigned to authority
- TaskMgmtSession taskSession = context.getTaskMgmtSession();
- List tasks = taskSession.findTaskInstances(authority);
+ List tasks;
+ if (state.equals(WorkflowTaskState.IN_PROGRESS))
+ {
+ TaskMgmtSession taskSession = context.getTaskMgmtSession();
+ tasks = taskSession.findTaskInstances(authority);
+ }
+ else
+ {
+ // Note: This method is not implemented by jBPM
+ tasks = findCompletedTaskInstances(context, authority);
+ }
+
+ // convert tasks to appropriate service response format
List workflowTasks = new ArrayList(tasks.size());
for (TaskInstance task : tasks)
{
- if (getWorkflowTaskState(task).equals(state))
- {
- WorkflowTask workflowTask = createWorkflowTask(task);
- workflowTasks.add(workflowTask);
- }
+ WorkflowTask workflowTask = createWorkflowTask(task);
+ workflowTasks.add(workflowTask);
}
return workflowTasks;
}
+
+ /**
+ * Gets the completed task list for the specified actor
+ *
+ * TODO: This method provides a query that's not in JBPM! Look to have JBPM implement this.
+ *
+ * @param jbpmContext the jbpm context
+ * @param actorId the actor to retrieve tasks for
+ * @return the tasks
+ */
+ private List findCompletedTaskInstances(JbpmContext jbpmContext, String actorId)
+ {
+ List result = null;
+ try
+ {
+ Session session = jbpmContext.getSession();
+ Query query = session.createQuery(COMPLETED_TASKS_QUERY);
+ query.setString("actorId", actorId);
+ result = query.list();
+ }
+ catch (Exception e)
+ {
+ throw new JbpmException("Couldn't get completed task instances list for actor '" + actorId + "'", e);
+ }
+ return result;
+ }
});
}
catch(JbpmException e)
{
- throw new WorkflowException("Failed to retrieve tasks assigned to authority '" + authority + "'", e);
+ throw new WorkflowException("Failed to retrieve tasks assigned to authority '" + authority + "' in state '" + state + "'", e);
}
}
-
+
/* (non-Javadoc)
* @see org.alfresco.repo.workflow.TaskComponent#getPooledTasks(java.util.List)
*/
diff --git a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java
index 5abfd40808..8ff75decdb 100644
--- a/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java
+++ b/source/java/org/alfresco/repo/workflow/jbpm/JBPMEngineTest.java
@@ -28,7 +28,6 @@ import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.alfresco.repo.workflow.TaskComponent;
import org.alfresco.repo.workflow.WorkflowComponent;
-import org.alfresco.repo.workflow.WorkflowDefinitionComponent;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -53,7 +52,6 @@ import org.springframework.core.io.ClassPathResource;
*/
public class JBPMEngineTest extends BaseSpringTest
{
- WorkflowDefinitionComponent workflowDefinitionComponent;
WorkflowComponent workflowComponent;
TaskComponent taskComponent;
WorkflowDefinition testWorkflowDef;
@@ -64,18 +62,17 @@ public class JBPMEngineTest extends BaseSpringTest
protected void onSetUpInTransaction() throws Exception
{
BPMEngineRegistry registry = (BPMEngineRegistry)applicationContext.getBean("bpm_engineRegistry");
- 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);
+ assertFalse(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
+ testWorkflowDef = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
assertNotNull(testWorkflowDef);
assertEquals("Test", testWorkflowDef.name);
assertEquals("1", testWorkflowDef.version);
- assertTrue(workflowDefinitionComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
+ assertTrue(workflowComponent.isDefinitionDeployed(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML));
// get valid node ref
NodeService nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
@@ -85,7 +82,7 @@ public class JBPMEngineTest extends BaseSpringTest
public void testGetWorkflowDefinitions()
{
- List workflowDefs = workflowDefinitionComponent.getDefinitions();
+ List workflowDefs = workflowComponent.getDefinitions();
assertNotNull(workflowDefs);
assertTrue(workflowDefs.size() > 0);
}
@@ -94,7 +91,7 @@ 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);
+ testWorkflowDef = workflowComponent.deployDefinition(processDef.getInputStream(), MimetypeMap.MIMETYPE_XML);
assertNotNull(testWorkflowDef);
assertEquals("Test", testWorkflowDef.name);
assertEquals("2", testWorkflowDef.version);
@@ -343,8 +340,13 @@ public class JBPMEngineTest extends BaseSpringTest
WorkflowTask updatedTask = taskComponent.endTask(tasks1.get(0).id, null);
assertNotNull(updatedTask);
assertEquals(WorkflowTaskState.COMPLETED, updatedTask.state);
+ List completedTasks = taskComponent.getAssignedTasks("System", WorkflowTaskState.COMPLETED);
+ assertNotNull(completedTasks);
+ assertEquals(1, completedTasks.size());
+ assertEquals(WorkflowTaskState.COMPLETED, completedTasks.get(0).state);
}
+
public void testGetTask()
{
WorkflowDefinition workflowDef = getTestDefinition();
diff --git a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java
index 88e13bf9d7..bd1388333c 100644
--- a/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java
+++ b/source/java/org/alfresco/service/cmr/workflow/WorkflowService.java
@@ -212,12 +212,13 @@ public interface WorkflowService
public WorkflowTask endTask(String taskId, String transition);
/**
- * Create a Workflow Package (a container of content to route through the Workflow)
+ * Create a Workflow Package (a container of content to route through the Workflow).
+ *
+ * If an existing container is supplied, it's supplemented with the workflow package aspect.
*
- * @param workflowDefinitionId workflow definition id
* @param container (optional) a pre-created container (e.g. folder, versioned folder or layered folder)
* @return the workflow package
*/
- public NodeRef createPackage(String workflowDefinitionId, NodeRef container);
+ public NodeRef createPackage(NodeRef container);
}