From 066d19a137f5c95017b385355b40e12f607537f0 Mon Sep 17 00:00:00 2001 From: quasi Date: Wed, 7 Aug 2013 06:01:37 +0000 Subject: [PATCH] Workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Geändert * Query für die Tskliste im CC auf gestartete Workflows beschränkt * Automatisches Starten eines Workflows beim Resetten verhindert, würde es eh' für den Publisher starten, nicht für die Autoren * Link zum Starten des Workflows wird nun auch im Zustand INIT angezeigt Wenn das Löschen des Workflows beim Publizieren per Config-Parameter com.arsdigita.cms.delete_workflow_after_publication abgeschalted wurde, sollte das Verhalten nun dem erwarteten entsprechen. Fehlt * Publizieren ist noch nicht vom WF abhängig git-svn-id: https://svn.libreccm.org/ccm/trunk@2296 8810af33-2d31-482b-a856-94f89814c4df --- .../query-getEnabledUserTasks.ora.pdl | 1 + .../query-getEnabledUserTasks.pg.pdl | 1 + .../ui/lifecycle/ItemLifecycleSelectForm.java | 4 +- .../cms/ui/workflow/ItemWorkflowItemPane.java | 3 +- .../arsdigita/workflow/simple/Workflow.java | 328 ++++++++++-------- 5 files changed, 182 insertions(+), 155 deletions(-) diff --git a/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.ora.pdl b/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.ora.pdl index 92706ce0d..5df66e58d 100755 --- a/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.ora.pdl +++ b/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.ora.pdl @@ -74,6 +74,7 @@ query getEnabledUserTasks { cw_tasks cw_tasks_proc where cw_tasks.task_id = cw_user_tasks.task_id and cw_user_tasks.task_id = cms_tasks.task_id + and cw_processes.process_state = 'started' and cms_tasks.task_type_id = cms_task_types.task_type_id and cw_tasks.task_state = 'enabled' and cw_tasks.parent_task_id = cw_processes.process_id diff --git a/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.pg.pdl b/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.pg.pdl index 6b365af49..28e4abaaf 100755 --- a/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.pg.pdl +++ b/ccm-cms/pdl/com/arsdigita/content-section/query-getEnabledUserTasks.pg.pdl @@ -74,6 +74,7 @@ query getEnabledUserTasks { cw_tasks cw_tasks_proc where cw_tasks.task_id = cw_user_tasks.task_id and cw_user_tasks.task_id = cms_tasks.task_id + and cw_processes.process_state = 'started' and cms_tasks.task_type_id = cms_task_types.task_type_id and cw_tasks.task_state = 'enabled' and cw_tasks.parent_task_id = cw_processes.process_id diff --git a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java index 8439a985e..5b25e7e01 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/lifecycle/ItemLifecycleSelectForm.java @@ -835,7 +835,9 @@ class ItemLifecycleSelectForm extends BaseForm { workflow.delete(); workflow = t.instantiateNewWorkflow(); workflow.setObject(item); - workflow.start(user); +/* Startring the workflow will probably do the wrong thing, because most of the time + * the current user would be a publisher, not an author */ +// workflow.start(user); workflow.save(); } } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java b/ccm-cms/src/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java index a9bdf3142..2e05df2cd 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/workflow/ItemWorkflowItemPane.java @@ -109,7 +109,8 @@ final class ItemWorkflowItemPane extends BaseWorkflowItemPane { public final boolean isVisible(final PageState state) { final Workflow workflow = m_workflow.getWorkflow(state); - return workflow.getProcessState() == Workflow.STOPPED; + // Start link should be visible if the workflow state is stopped or init + return (workflow.getProcessState() == Workflow.STOPPED || workflow.getProcessState() == Workflow.INIT); } private class Listener implements ActionListener { diff --git a/ccm-core/src/com/arsdigita/workflow/simple/Workflow.java b/ccm-core/src/com/arsdigita/workflow/simple/Workflow.java index 79d85b93b..abb7faed4 100755 --- a/ccm-core/src/com/arsdigita/workflow/simple/Workflow.java +++ b/ccm-core/src/com/arsdigita/workflow/simple/Workflow.java @@ -44,8 +44,8 @@ import java.util.Map; import org.apache.log4j.Logger; /** - * Represents a process instance that is assigned to a particular - * process that is associated with some object. + * Represents a process instance that is assigned to a particular process that + * is associated with some object. * * @author Khy Huang * @author Stefan Deusch @@ -53,66 +53,66 @@ import org.apache.log4j.Logger; * @author Karl Goldstein * @version $Id: Workflow.java 1278 2006-07-27 09:09:51Z cgyg9330 $ * - **/ + * + */ public class Workflow extends Task { public static final String BASE_DATA_OBJECT_TYPE = - "com.arsdigita.workflow.simple.Workflow"; - + "com.arsdigita.workflow.simple.Workflow"; private static final Logger s_log = Logger.getLogger(Workflow.class); - private OID m_ACSObjectOID = null; public static final String ACS_OBJECT = "object"; private static final String PROCESS_STATE = "processState"; private static final String WF_TASKS = "wfTasks"; - public static final String TASK_WORKFLOW = "taskWf"; - + public static final String TASK_WORKFLOW = "taskWf"; private static final String PROCESS_DEF_ID = "processDefinitionID"; - // class variables, enums of constants public final static int NONE = -1; public final static int STARTED = 0; public final static int STOPPED = 1; public final static int DELETED = 2; - public final static int INIT = 3; + public final static int INIT = 3; /** - * Creates a new workflow process. The properties of this object - * are not made persistent until the save method is called. + * Creates a new workflow process. The properties of this object are not + * made persistent until the + * save method is called. * * @param label the label * @param description the description - **/ + * + */ public Workflow(String label, String description) { super(BASE_DATA_OBJECT_TYPE); - initAttributes(label,description); + initAttributes(label, description); } /** * Creates a new workflow process with the properties - * label and description set to null. - * Properties of this object are not made persistent until the - * save method is called. If save() is called - * without setting these properties, an IllegalArgumentException - * will be thrown. - **/ + * label and + * description set to null. Properties of this object are not + * made persistent until the + * save method is called. If save() is called without setting + * these properties, an IllegalArgumentException will be thrown. + * + */ public Workflow() { super(BASE_DATA_OBJECT_TYPE); } - /** * Restores a workflow process from a task data object. * * @param workflowDataObject - **/ + * + */ public Workflow(DataObject workflowDataObject) { super(workflowDataObject); - DataObject object = (DataObject)get(ACS_OBJECT); - if (object != null) { - m_ACSObjectOID = object.getOID(); - } + DataObject object = (DataObject) get(ACS_OBJECT); + if (object != null) { + m_ACSObjectOID = object.getOID(); + } } /** @@ -120,7 +120,8 @@ public class Workflow extends Task { * * @param type the object type * @see com.arsdigita.persistence.metadata.ObjectType - **/ + * + */ protected Workflow(ObjectType type) { super(type); } @@ -130,42 +131,46 @@ public class Workflow extends Task { * * @param typeName the type name * - **/ + * + */ protected Workflow(String typeName) { super(typeName); } /** - * Restores a workflow process using an OID. + * Restores a workflow process using an OID. * * @param oid the OID * @see com.arsdigita.persistence.OID * - **/ + * + */ public Workflow(OID oid) throws DataObjectNotFoundException { super(oid); } /** - * Restores a workflow process using a BigDecimal ID. + * Restores a workflow process using a BigDecimal ID. * - * @param id the BigDecimal ID of this object. An OID will be - * created implicitly with the BASE_DATA_OBJECT_TYPE constant - * specified in this file. - **/ + * @param id the BigDecimal ID of this object. An OID will be created + * implicitly with the BASE_DATA_OBJECT_TYPE constant specified in this + * file. + * + */ public Workflow(BigDecimal id) throws DataObjectNotFoundException { this(new OID(BASE_DATA_OBJECT_TYPE, id)); } /** - * Initializes the internal state depending on whether - * this is a new or a restored instance. - **/ + * Initializes the internal state depending on whether this is a new or a + * restored instance. + * + */ protected void initialize() { super.initialize(); if (!isNew()) { - DataObject object = (DataObject)get(ACS_OBJECT); + DataObject object = (DataObject) get(ACS_OBJECT); if (object != null) { m_ACSObjectOID = object.getOID(); } @@ -184,13 +189,13 @@ public class Workflow extends Task { return BASE_DATA_OBJECT_TYPE; } - /** * Adds a task to this process. (persistent operation) * * @param task the task to add to this process * @see Task - **/ + * + */ public void addTask(Task task) { task.setParent(this); if (getProcessState() == STARTED) { @@ -201,20 +206,21 @@ public class Workflow extends Task { updateState(); } - /** - * Deletes a task. (perisistent operation). + * Deletes a task. (perisistent operation). * * @param task to be removed - **/ + * + */ public void removeTask(Task task) { - remove(WF_TASKS,task); + remove(WF_TASKS, task); //task.delete() } /** * Removes all tasks from this workflow. (persistent operation) - **/ + * + */ public void removeAllTasks() { DataAssociation da = getTaskAssociation(); da.clear(); @@ -230,7 +236,8 @@ public class Workflow extends Task { * * @param user the user * - **/ + * + */ public void save(User user) throws ProcessException { //add logging information save(); @@ -240,31 +247,33 @@ public class Workflow extends Task { * Returns the number of task in this process. * * @return the numnber of tasks in the workflow - **/ + * + */ public int getTaskCount() { return (new Long(getTaskAssociation().cursor().size())).intValue(); } - // ---------------- START: state methods -------------------------- /** * Stops the process. (persistent operation) * * @param user the user that stopped the process * - **/ + * + */ public void stop(User user) { setProcessState(STOPPED); save(); } /** - * Starts the process. This method marks all the tasks as - * active when called the first time. (persistent operation) + * Starts the process. This method marks all the tasks as active when called + * the first time. (persistent operation) * * @param user the user that starts the process * - **/ + * + */ public void start(User user) { int processState = getProcessState(); @@ -280,11 +289,12 @@ public class Workflow extends Task { } /** - * Gets the process spinning. This method also - * marks all the tasks as active. + * Gets the process spinning. This method also marks all the tasks as + * active. * * - **/ + * + */ protected void startInternal() { TaskCollection tasks = getTaskCollection(); @@ -324,18 +334,19 @@ public class Workflow extends Task { * */ public int getProcessState() { - return getProcessStateInt((String)get(PROCESS_STATE)); + return getProcessStateInt((String) get(PROCESS_STATE)); } /** - * Internal method to - * set the state from the DB, 'stopped', 'started','deleted', 'init' are allowed + * Internal method to set the state from the DB, 'stopped', + * 'started','deleted', 'init' are allowed * * @param state the process state * - **/ + * + */ private void setProcessState(int state) { - set(PROCESS_STATE,getProcessStateStr(state)); + set(PROCESS_STATE, getProcessStateStr(state)); if (!isNew()) { save(); } @@ -345,7 +356,8 @@ public class Workflow extends Task { * Sets the Object that this workflow is applied to. * * @param o the object to which to apply this workflow. - **/ + * + */ public void setObject(ACSObject o) { m_ACSObjectOID = o.getOID(); set(ACS_OBJECT, o); @@ -354,16 +366,15 @@ public class Workflow extends Task { /** * Set the object id * - **/ + * + */ public void setObjectID(BigDecimal id) { - m_ACSObjectOID = new OID(ACSObject.BASE_DATA_OBJECT_TYPE,id); + m_ACSObjectOID = new OID(ACSObject.BASE_DATA_OBJECT_TYPE, id); try { - set(ACS_OBJECT, DomainObjectFactory.newInstance - (m_ACSObjectOID)); + set(ACS_OBJECT, DomainObjectFactory.newInstance(m_ACSObjectOID)); } catch (DataObjectNotFoundException e) { s_log.error("unable to locate the ID for the workflow"); - throw new UncheckedWrapperException - ("Unable to locate object corresponding to ID " + id, e); + throw new UncheckedWrapperException("Unable to locate object corresponding to ID " + id, e); } } @@ -371,7 +382,8 @@ public class Workflow extends Task { * Helper method that converts the state string in persistence to * WorkflowProcess object state ids * - **/ + * + */ private int getProcessStateInt(String state) { if (state.equals("stopped")) { return STOPPED; @@ -386,45 +398,50 @@ public class Workflow extends Task { } /** - * Helper method that converts the state ids in WorkflowProcess object - * to state string in persistence + * Helper method that converts the state ids in WorkflowProcess object to + * state string in persistence * * @return the persistence state string * - **/ + * + */ private String getProcessStateStr(int state) { switch (state) { - case STARTED: return "started"; - case STOPPED: return "stopped"; - case DELETED: return "deleted"; - case INIT: return "init"; - case NONE: return "none"; + case STARTED: + return "started"; + case STOPPED: + return "stopped"; + case DELETED: + return "deleted"; + case INIT: + return "init"; + case NONE: + return "none"; } return null; } // ---------------- END: state methods ------------------- - - /** * Returns an iterator for the tasks in this process. * * @return the list of all tasks. * - **/ + * + */ public Iterator getTasks() { return new DomainCollectionIterator(getTaskCollection()); } - /** * The data association for the tasks in workflow process. * * @return the data collection * - **/ + * + */ private DataAssociation getTaskAssociation() { - return (DataAssociation)get(WF_TASKS); + return (DataAssociation) get(WF_TASKS); } /** @@ -432,12 +449,13 @@ public class Workflow extends Task { * * @return an interator over enabled tasks. * - **/ + * + */ public Iterator getEnabledTasks() { if (getProcessState() == DELETED || getProcessState() == STOPPED) { - if ( s_log.isDebugEnabled() ) { - s_log.debug("No enabled tasks. Process state is " + - getProcessState()); + if (s_log.isDebugEnabled()) { + s_log.debug("No enabled tasks. Process state is " + + getProcessState()); } return Collections.EMPTY_LIST.iterator(); } @@ -448,7 +466,7 @@ public class Workflow extends Task { FilterFactory factory = tasks.getFilterFactory(); CompoundFilter filter = factory.and(); filter.addFilter(factory.equals(Task.TASK_STATE, Task.getStateString(Task.ENABLED))); - filter.addFilter(factory.equals(Task.IS_ACTIVE, "1" )); + filter.addFilter(factory.equals(Task.IS_ACTIVE, "1")); tasks.addFilter(filter); LinkedList enabledTasks = new LinkedList(); @@ -468,7 +486,8 @@ public class Workflow extends Task { * * @return an iterator over finished tasks. * - **/ + * + */ public Iterator getFinishedTasks() { TaskCollection tasksCollection = getTaskCollection(); Filter filter = tasksCollection.addFilter("taskState = :taskState"); @@ -478,13 +497,14 @@ public class Workflow extends Task { /** * @return an iterator over all overdue tasks in the process. - **/ + * + */ public Iterator getOverdueTasks() { HashSet tasksSet = new HashSet(); TaskCollection tasksCollection = getTaskCollection(); - while ( tasksCollection.next() ) { + while (tasksCollection.next()) { Task task = (Task) tasksCollection.getDomainObject(); - if ( task instanceof UserTask && ((UserTask) task).isOverdue() ) { + if (task instanceof UserTask && ((UserTask) task).isOverdue()) { tasksSet.add(task); } } @@ -499,14 +519,16 @@ public class Workflow extends Task { * * @return the ACS object that this process is based on. * - **/ + * + */ public OID getObjectOID() { return m_ACSObjectOID; } /** * Get the ACSObject this Workflow is associated with. - **/ + * + */ public ACSObject getObject() { OID objOID = getObjectOID(); if (objOID == null) { @@ -514,38 +536,40 @@ public class Workflow extends Task { } else { try { return (ACSObject) DomainObjectFactory. - newInstance(getObjectOID()); + newInstance(getObjectOID()); } catch (DataObjectNotFoundException de) { - throw new UncheckedWrapperException("Could not load object with OID " + - getObjectOID(), - de); + throw new UncheckedWrapperException("Could not load object with OID " + + getObjectOID(), + de); } } } /** - * Removes a task from the underlying - * workflow process definition. + * Removes a task from the underlying workflow process definition. * * @param task the task to be removed - * @param dependentList the task definitions that are dependent on - * the passed in task definition + * @param dependentList the task definitions that are dependent on the + * passed in task definition * - **/ + * + */ public void removeTask(Task task, Iterator dependentList) { Task dependentTask; while (dependentList.hasNext()) { - dependentTask = (Task)dependentList.next(); + dependentTask = (Task) dependentList.next(); dependentTask.removeFinishedListener(task); //dependentTask.updateState(); } } /** - * Override the update method, workflow is finished if all its task are completed + * Override the update method, workflow is finished if all its task are + * completed * * - **/ + * + */ synchronized void updateState() { super.updateState(); @@ -591,16 +615,14 @@ public class Workflow extends Task { } } - - /** - * Performs a deep clone of the workflow. All tasks - * are cloned as well. The cloned copy is saved to persistent - * storage before returning. + * Performs a deep clone of the workflow. All tasks are cloned as well. The + * cloned copy is saved to persistent storage before returning. * * @return the cloned workflow process. * - **/ + * + */ public synchronized Object clone() { Workflow workflowClone = new Workflow(getLabel(), getDescription()); //copyAttributes(workflowClone); @@ -613,7 +635,7 @@ public class Workflow extends Task { Map taskToCloneMap = new HashMap(); Task dependOn, dependOnClone; Task task; - Task taskClone,taskListenerClone, listener; + Task taskClone, taskListenerClone, listener; Iterator dependencies; Iterator tasks, finishedListeners; @@ -621,10 +643,10 @@ public class Workflow extends Task { tasks = getTasks(); while (tasks.hasNext()) { - task = (Task)tasks.next(); + task = (Task) tasks.next(); taskClone = null; try { - taskClone = (Task)(task.clone()); + taskClone = (Task) (task.clone()); taskClone.removeAllFinishedListeners(); taskClone.save(); taskClone.removeAllDependencies(); @@ -642,16 +664,16 @@ public class Workflow extends Task { tasks = getTasks(); while (tasks.hasNext()) { - task = (Task)tasks.next(); - taskClone = (Task)taskToCloneMap.get(task); + task = (Task) tasks.next(); + taskClone = (Task) taskToCloneMap.get(task); // Clone also copies the references to previous environment, // so we remove those // Copy dependencies of one task definition to the clone one dependencies = task.getDependencies(); while (dependencies.hasNext()) { - dependOn = (Task)dependencies.next(); - dependOnClone = (Task)taskToCloneMap.get(dependOn); + dependOn = (Task) dependencies.next(); + dependOnClone = (Task) taskToCloneMap.get(dependOn); taskClone.addDependency(dependOnClone); } @@ -659,18 +681,18 @@ public class Workflow extends Task { //is not a dependency then clone them. finishedListeners = task.getFinishedListeners(); while (finishedListeners.hasNext()) { - listener = (Task)finishedListeners.next(); + listener = (Task) finishedListeners.next(); // Listeners to exclude are : // 1. the containing workflow // 2. Task that depend on this task; When we added dependency // a listener was already registered. - if (!listener.equals(this) && - !listener.isDependency(task)) { + if (!listener.equals(this) + && !listener.isDependency(task)) { //Clone the listener and add clone task as listener try { - taskListenerClone = (Task)listener.clone(); + taskListenerClone = (Task) listener.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); @@ -688,7 +710,8 @@ public class Workflow extends Task { /** * Overrides the enable method (since the behavior is a little different). * - **/ + * + */ public void enable() { int taskState = getState(); @@ -701,26 +724,27 @@ public class Workflow extends Task { //If we were in finished state, we need to move back to //INIT state. In INIT State all tasks are disabled. /* - if (taskState == FINISHED) { - Iterator itr = getTasks(); + if (taskState == FINISHED) { + Iterator itr = getTasks(); - while (itr.hasNext()) { - tempTask = (Task)itr.next(); - tempTask.disable(); - } - setProcessState(INIT); - start(null); - } else if (getProcessState() == INIT) { - start(null); - } - */ + while (itr.hasNext()) { + tempTask = (Task)itr.next(); + tempTask.disable(); + } + setProcessState(INIT); + start(null); + } else if (getProcessState() == INIT) { + start(null); + } + */ } /** * On a disable event, stops the workflow. * - **/ + * + */ public void disableEvt() { Task tempTask = null; stop(null); @@ -728,7 +752,7 @@ public class Workflow extends Task { Iterator itr = getTasks(); while (itr.hasNext()) { - tempTask = (Task)itr.next(); + tempTask = (Task) itr.next(); tempTask.disable(); } setProcessState(INIT); @@ -737,7 +761,8 @@ public class Workflow extends Task { /** * Set the template from which this Workflow was instantiated. - **/ + * + */ public void setWorkflowTemplate(WorkflowTemplate template) { if (template != null) { set(PROCESS_DEF_ID, template.getID()); @@ -748,17 +773,18 @@ public class Workflow extends Task { /** * Get the template from which this workflow was instantiated. - **/ + * + */ public WorkflowTemplate getWorkflowTemplate() { BigDecimal templateID = (BigDecimal) get(PROCESS_DEF_ID); if (templateID != null) { try { return (WorkflowTemplate) DomainObjectFactory. - newInstance(new OID(WorkflowTemplate.BASE_DATA_OBJECT_TYPE, - templateID)); + newInstance(new OID(WorkflowTemplate.BASE_DATA_OBJECT_TYPE, + templateID)); } catch (DataObjectNotFoundException de) { throw new UncheckedWrapperException("Could not load WorkflowTemplate with ID " + templateID, - de); + de); } } else { return null; @@ -773,28 +799,25 @@ public class Workflow extends Task { public static BigDecimal getItemID(BigDecimal workflowId) { BigDecimal objectID = null; Session session = SessionManager.getSession(); - DataQuery query = session.retrieveQuery - ("com.arsdigita.workflow.simple.getProcesses"); + DataQuery query = session.retrieveQuery("com.arsdigita.workflow.simple.getProcesses"); query.addEqualsFilter("id", workflowId); if (query.next()) { - objectID = (BigDecimal)query.get("processObjectID"); + objectID = (BigDecimal) query.get("processObjectID"); query.close(); } return objectID; } /* static methods to retrieve the workflow associated with an object */ - public static BigDecimal getObjectWorkflowID(BigDecimal id) { BigDecimal workflowID = null; final Session session = SessionManager.getSession(); - final DataQuery query = session.retrieveQuery - ("com.arsdigita.workflow.simple.getProcesses"); - Filter filter= query.addFilter("processObjectID = :object_id"); + final DataQuery query = session.retrieveQuery("com.arsdigita.workflow.simple.getProcesses"); + Filter filter = query.addFilter("processObjectID = :object_id"); filter.set("object_id", id); if (query.next()) { - workflowID = (BigDecimal)query.get("processID"); + workflowID = (BigDecimal) query.get("processID"); query.close(); } @@ -808,8 +831,7 @@ public class Workflow extends Task { public static Workflow getObjectWorkflow(BigDecimal id) { final BigDecimal workflowID; final Session session = SessionManager.getSession(); - final DataQuery query = session.retrieveQuery - ("com.arsdigita.workflow.simple.getProcesses"); + final DataQuery query = session.retrieveQuery("com.arsdigita.workflow.simple.getProcesses"); final Filter filter = query.addFilter("processObjectID = :object_id"); filter.set("object_id", id);