Break class cycles between Workflow and Step in order to prepare for JSPWIKI-304 (Workflows are not Serializable)
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/tasks/auth/SaveUserProfileTask.java b/jspwiki-main/src/main/java/org/apache/wiki/tasks/auth/SaveUserProfileTask.java
index 3cb09a0..18325b3 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/tasks/auth/SaveUserProfileTask.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/tasks/auth/SaveUserProfileTask.java
@@ -48,7 +48,7 @@
@Override
public Outcome execute() throws WikiException {
// Retrieve user profile
- final UserProfile profile = ( UserProfile )getWorkflow().getAttribute( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE );
+ final UserProfile profile = ( UserProfile )getWorkflowContext().get( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE );
// Save the profile (userdatabase will take care of timestamps for us)
m_engine.getManager( UserManager.class ).getUserDatabase().save( profile );
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/PreSaveWikiPageTask.java b/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/PreSaveWikiPageTask.java
index c2ed0ac..5e65649 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/PreSaveWikiPageTask.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/PreSaveWikiPageTask.java
@@ -19,14 +19,12 @@
package org.apache.wiki.tasks.pages;
import org.apache.wiki.api.core.Context;
-import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Page;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.filters.FilterManager;
import org.apache.wiki.tasks.TasksManager;
import org.apache.wiki.workflow.Outcome;
import org.apache.wiki.workflow.Task;
-import org.apache.wiki.workflow.Workflow;
import org.apache.wiki.workflow.WorkflowManager;
import java.security.Principal;
@@ -60,10 +58,6 @@
*/
@Override
public Outcome execute() throws WikiException {
- // Retrieve attributes
- final Engine engine = m_context.getEngine();
- final Workflow workflow = getWorkflow();
-
// Get the wiki page
final Page page = m_context.getPage();
@@ -76,11 +70,11 @@
}
// Run the pre-save filters. If any exceptions, add error to list, abort, and redirect
- final String saveText = engine.getManager( FilterManager.class ).doPreSaveFiltering(m_context, m_proposedText);
+ final String saveText = m_context.getEngine().getManager( FilterManager.class ).doPreSaveFiltering(m_context, m_proposedText);
// Stash the wiki context, old and new text as workflow attributes
- workflow.setAttribute( WorkflowManager.WF_WP_SAVE_ATTR_PRESAVE_WIKI_CONTEXT, m_context );
- workflow.setAttribute( WorkflowManager.WF_WP_SAVE_FACT_PROPOSED_TEXT, saveText );
+ getWorkflowContext().put( WorkflowManager.WF_WP_SAVE_ATTR_PRESAVE_WIKI_CONTEXT, m_context );
+ getWorkflowContext().put( WorkflowManager.WF_WP_SAVE_FACT_PROPOSED_TEXT, saveText );
return Outcome.STEP_COMPLETE;
}
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/SaveWikiPageTask.java b/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/SaveWikiPageTask.java
index 3f83d08..0063c40 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/SaveWikiPageTask.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/tasks/pages/SaveWikiPageTask.java
@@ -51,8 +51,8 @@
@Override
public Outcome execute() throws WikiException {
// Retrieve attributes
- final Context context = ( Context ) getWorkflow().getAttribute( WorkflowManager.WF_WP_SAVE_ATTR_PRESAVE_WIKI_CONTEXT );
- final String proposedText = (String) getWorkflow().getAttribute( WorkflowManager.WF_WP_SAVE_FACT_PROPOSED_TEXT );
+ final Context context = ( Context )getWorkflowContext().get( WorkflowManager.WF_WP_SAVE_ATTR_PRESAVE_WIKI_CONTEXT );
+ final String proposedText = ( String )getWorkflowContext().get( WorkflowManager.WF_WP_SAVE_FACT_PROPOSED_TEXT );
final Engine engine = context.getEngine();
final Page page = context.getPage();
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/AbstractStep.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/AbstractStep.java
index e545990..414aa20 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/AbstractStep.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/AbstractStep.java
@@ -20,7 +20,6 @@
import org.apache.wiki.api.exceptions.WikiException;
-import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
@@ -53,7 +52,10 @@
private final Map< Outcome, Step > m_successors;
- private Workflow m_workflow;
+ private int workflowId;
+
+ /** attribute map. */
+ private Map< String, Object > workflowContext;
private Outcome m_outcome;
@@ -63,7 +65,7 @@
/**
* Protected constructor that creates a new Step with a specified message key. After construction, the method
- * {@link #setWorkflow(Workflow)} should be called.
+ * {@link #setWorkflow(int, Map)} should be called.
*
* @param messageKey the Step's message key, such as {@code decision.editPageApproval}. By convention, the message prefix should
* be a lower-case version of the Step's type, plus a period (<em>e.g.</em>, {@code task.} and {@code decision.}).
@@ -82,13 +84,14 @@
/**
* Constructs a new Step belonging to a specified Workflow and having a specified message key.
*
- * @param workflow the workflow the Step belongs to
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
* @param messageKey the Step's message key, such as {@code decision.editPageApproval}. By convention, the message prefix should
* be a lower-case version of the Step's type, plus a period (<em>e.g.</em>, {@code task.} and {@code decision.}).
*/
- public AbstractStep( final Workflow workflow, final String messageKey ) {
+ public AbstractStep( final int workflowId, final Map< String, Object > workflowContext, final String messageKey ) {
this( messageKey );
- setWorkflow( workflow );
+ setWorkflow( workflowId, workflowContext );
}
/**
@@ -133,16 +136,6 @@
/**
* {@inheritDoc}
*/
- public final Serializable[] getMessageArguments() {
- if( m_workflow == null ) {
- return new Serializable[ 0 ];
- }
- return m_workflow.getMessageArguments();
- }
-
- /**
- * {@inheritDoc}
- */
public final String getMessageKey() {
return m_key;
}
@@ -157,16 +150,6 @@
/**
* {@inheritDoc}
*/
- public Principal getOwner() {
- if( m_workflow == null ) {
- return null;
- }
- return m_workflow.getOwner();
- }
-
- /**
- * {@inheritDoc}
- */
public final Date getStartTime() {
return m_start;
}
@@ -174,13 +157,6 @@
/**
* {@inheritDoc}
*/
- public final synchronized Workflow getWorkflow() {
- return m_workflow;
- }
-
- /**
- * {@inheritDoc}
- */
public final boolean isCompleted() {
return m_completed;
}
@@ -235,12 +211,22 @@
// --------------------------Helper methods--------------------------
/**
- * method that sets the parent Workflow post-construction.
+ * method that sets the parent Workflow id and context post-construction.
*
- * @param workflow the parent workflow to set
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
*/
- public final synchronized void setWorkflow( final Workflow workflow ) {
- m_workflow = workflow;
+ public final synchronized void setWorkflow( final int workflowId, final Map< String, Object > workflowContext ) {
+ this.workflowId = workflowId;
+ this.workflowContext = workflowContext;
+ }
+
+ public int getWorkflowId() {
+ return workflowId;
+ }
+
+ public Map< String, Object > getWorkflowContext() {
+ return workflowContext;
}
/**
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Decision.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Decision.java
index dbbabed..07749c1 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Decision.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Decision.java
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
@@ -61,13 +62,14 @@
/**
* Constructs a new Decision for a required "actor" Principal, having a default Outcome.
*
- * @param workflow the parent Workflow object
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
* @param messageKey the i18n message key that represents the message the actor will see
* @param actor the Principal (<em>e.g.</em>, a WikiPrincipal, Role, GroupPrincipal) who is required to select an appropriate Outcome
* @param defaultOutcome the Outcome that the user interface will recommend as the default choice
*/
- public Decision( final Workflow workflow, final String messageKey, final Principal actor, final Outcome defaultOutcome ) {
- super( workflow, messageKey );
+ public Decision( final int workflowId, final Map< String, Object > workflowContext, final String messageKey, final Principal actor, final Outcome defaultOutcome ) {
+ super( workflowId, workflowContext, messageKey );
m_actor = actor;
m_defaultOutcome = defaultOutcome;
m_facts = new ArrayList<>();
@@ -104,14 +106,7 @@
*/
public void decide( final Outcome outcome ) throws WikiException {
super.setOutcome( outcome );
-
- // If current workflow is waiting for input, restart it and remove Decision from DecisionQueue
- final Workflow w = getWorkflow();
- if( w.getCurrentState() == Workflow.WAITING && this.equals( w.getCurrentStep() ) ) {
- WorkflowEventEmitter.fireEvent( this, WorkflowEvent.DQ_REMOVAL );
- // Restart workflow
- w.restart();
- }
+ WorkflowEventEmitter.fireEvent( this, WorkflowEvent.DQ_REMOVAL );
}
/**
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/DefaultWorkflowManager.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/DefaultWorkflowManager.java
index d837611..723b5c0 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/DefaultWorkflowManager.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/DefaultWorkflowManager.java
@@ -18,19 +18,20 @@
*/
package org.apache.wiki.workflow;
+import org.apache.log4j.Logger;
import org.apache.wiki.api.core.Engine;
import org.apache.wiki.api.core.Session;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.auth.AuthorizationManager;
import org.apache.wiki.auth.acl.UnresolvedPrincipal;
import org.apache.wiki.event.WikiEvent;
-import org.apache.wiki.event.WikiEventManager;
import org.apache.wiki.event.WorkflowEvent;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -45,6 +46,8 @@
*/
public class DefaultWorkflowManager implements WorkflowManager {
+ private static final Logger LOG = Logger.getLogger( DefaultWorkflowManager.class );
+
private final DecisionQueue m_queue = new DecisionQueue();
private final Set< Workflow > m_workflows;
private final Map< String, Principal > m_approvers;
@@ -52,15 +55,13 @@
private Engine m_engine = null;
/**
- * Constructs a new WorkflowManager, with an empty workflow cache. New Workflows are automatically assigned unique identifiers,
- * starting with 1.
+ * Constructs a new WorkflowManager, with an empty workflow cache.
*/
public DefaultWorkflowManager() {
- m_next = 1;
m_workflows = ConcurrentHashMap.newKeySet();
m_approvers = new ConcurrentHashMap<>();
m_completed = new CopyOnWriteArrayList<>();
- WikiEventManager.addWikiEventListener( WorkflowEventEmitter.get(), this );
+ WorkflowEventEmitter.registerListener( this );
}
/**
@@ -68,8 +69,6 @@
*/
@Override
public void start( final Workflow workflow ) throws WikiException {
- m_workflows.add( workflow );
- workflow.setId( nextId() );
workflow.start();
}
@@ -176,19 +175,6 @@
return m_queue;
}
- private volatile int m_next;
-
- /**
- * Returns the next available unique identifier, which is subsequently incremented.
- *
- * @return the id
- */
- private synchronized int nextId() {
- final int current = m_next;
- m_next++;
- return current;
- }
-
/**
* {@inheritDoc}
*/
@@ -251,9 +237,6 @@
* @param workflow the workflow to add
*/
protected void add( final Workflow workflow ) {
- if ( workflow.getId() == Workflow.ID_NOT_SET ) {
- workflow.setId( nextId() );
- }
m_workflows.add( workflow );
}
@@ -271,7 +254,21 @@
}
protected void removeFromDecisionQueue( final Decision decision ) {
- getDecisionQueue().remove( decision );
+ // If current workflow is waiting for input, restart it and remove Decision from DecisionQueue
+ final int workflowId = decision.getWorkflowId();
+ final Optional< Workflow > optw = m_workflows.stream().filter( w -> w.getId() == workflowId ).findAny();
+ if( optw.isPresent() ) {
+ final Workflow w = optw.get();
+ if( w.getCurrentState() == Workflow.WAITING && decision.equals( w.getCurrentStep() ) ) {
+ getDecisionQueue().remove( decision );
+ // Restart workflow
+ try {
+ w.restart();
+ } catch( final WikiException e ) {
+ LOG.error( "restarting workflow #" + w.getId() + " caused " + e.getMessage(), e );
+ }
+ }
+ }
}
protected void addToDecisionQueue( final Decision decision ) {
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleDecision.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleDecision.java
index 181c355..bae296a 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleDecision.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleDecision.java
@@ -19,30 +19,27 @@
package org.apache.wiki.workflow;
import java.security.Principal;
+import java.util.Map;
+
/**
- * Decision subclass that includes two available Outcomes:
- * {@link Outcome#DECISION_APPROVE} or {@link Outcome#DECISION_DENY}.
- * The Decision is reassignable, and the default Outcome is
- * {@link Outcome#DECISION_APPROVE}.
- *
+ * Decision subclass that includes two available Outcomes: {@link Outcome#DECISION_APPROVE} or {@link Outcome#DECISION_DENY}.
+ * The Decision is reassignable, and the default Outcome is {@link Outcome#DECISION_APPROVE}.
*/
-public class SimpleDecision extends Decision
-{
+public class SimpleDecision extends Decision {
private static final long serialVersionUID = 8192213077644617341L;
/**
* Constructs a new SimpleDecision assigned to a specified actor.
- * @param workflow the parent Workflow
- * @param messageKey the message key that describes the Decision, which
- * will be presented in the UI
- * @param actor the Principal (<em>e.g.</em>, WikiPrincipal,
- * GroupPrincipal, Role) who will decide
+ *
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
+ * @param messageKey the message key that describes the Decision, which will be presented in the UI
+ * @param actor the Principal (<em>e.g.</em>, WikiPrincipal, GroupPrincipal, Role) who will decide
*/
- public SimpleDecision( Workflow workflow, String messageKey, Principal actor )
- {
- super( workflow, messageKey, actor, Outcome.DECISION_APPROVE );
+ public SimpleDecision( final int workflowId, final Map< String, Object > workflowContext, final String messageKey, final Principal actor ) {
+ super( workflowId, workflowContext, messageKey, actor, Outcome.DECISION_APPROVE );
// Add the other default outcomes
super.addSuccessor( Outcome.DECISION_DENY, null );
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleNotification.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleNotification.java
index d2cfdb0..44d88a2 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleNotification.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/SimpleNotification.java
@@ -18,59 +18,50 @@
*/
package org.apache.wiki.workflow;
-import java.security.Principal;
-
import org.apache.wiki.api.exceptions.WikiException;
+import java.security.Principal;
+import java.util.Map;
+
/**
- * Decision subclass used for notifications that includes only one available Outcome:
- * {@link Outcome#DECISION_ACKNOWLEDGE}. The Decision is not reassignable, and
- * the default Outcome is {@link Outcome#DECISION_ACKNOWLEDGE}.
+ * Decision subclass used for notifications that includes only one available Outcome: {@link Outcome#DECISION_ACKNOWLEDGE}. The Decision is
+ * not reassignable, and the default Outcome is {@link Outcome#DECISION_ACKNOWLEDGE}.
*
* @since 2.5
*/
-public final class SimpleNotification extends Decision
-{
+public final class SimpleNotification extends Decision {
private static final long serialVersionUID = -3392947495169819527L;
/**
- * Constructs a new SimpleNotification object with a supplied message key,
- * associated Workflow, and named actor who must acknowledge the message.
- * The notification is placed in the Principal's list of queued Decisions.
- * Because the only available Outcome is
- * {@link Outcome#DECISION_ACKNOWLEDGE}, the actor can only acknowledge the
- * message.
+ * Constructs a new SimpleNotification object with a supplied message key, associated Workflow, and named actor who must acknowledge
+ * the message. The notification is placed in the Principal's list of queued Decisions. Because the only available Outcome is
+ * {@link Outcome#DECISION_ACKNOWLEDGE}, the actor can only acknowledge the message.
*
- * @param workflow
- * the Workflow to associate this notification with
- * @param messageKey
- * the message key
- * @param actor
- * the Principal who will acknowledge the message
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
+ * @param messageKey the message key
+ * @param actor the Principal who will acknowledge the message
*/
- public SimpleNotification( Workflow workflow, String messageKey, Principal actor )
- {
- super( workflow, messageKey, actor, Outcome.DECISION_ACKNOWLEDGE );
+ public SimpleNotification( final int workflowId, final Map< String, Object > workflowContext, final String messageKey, final Principal actor ) {
+ super( workflowId, workflowContext, messageKey, actor, Outcome.DECISION_ACKNOWLEDGE );
}
/**
- * Convenience method that simply calls {@link #decide(Outcome)}
- * with the value {@link Outcome#DECISION_ACKNOWLEDGE}.
+ * Convenience method that simply calls {@link #decide(Outcome)} with the value {@link Outcome#DECISION_ACKNOWLEDGE}.
+ *
* @throws WikiException never
*/
- public void acknowledge() throws WikiException
- {
+ public void acknowledge() throws WikiException {
this.decide( Outcome.DECISION_ACKNOWLEDGE );
}
/**
- * Notifications cannot be re-assigned, so this method always returns
- * <code>false</code>.
- * @return <code>false</code> always
+ * Notifications cannot be re-assigned, so this method always returns <code>false</code>.
+ *
+ * @return <code>false</code> always.
*/
- public boolean isReassignable()
- {
+ public boolean isReassignable() {
return false;
}
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Step.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Step.java
index 50e3327..5d890cc 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Step.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Step.java
@@ -25,6 +25,8 @@
import java.util.Collection;
import java.util.Date;
import java.util.List;
+import java.util.Map;
+
/**
* <p>
@@ -124,14 +126,6 @@
String getMessageKey();
/**
- * Returns the message arguments for this Step, typically by delegating to the parent Workflow's {@link Workflow#getMessageArguments()}
- * method.
- *
- * @return the message arguments.
- */
- Serializable[] getMessageArguments();
-
- /**
* Returns the Outcome of this Step's processing; by default, {@link Outcome#STEP_CONTINUE}.
*
* @return the outcome
@@ -181,13 +175,6 @@
void setOutcome( Outcome outcome );
/**
- * Convenience method that returns the owner of the Workflow by delegating to {@link Workflow#getOwner()}.
- *
- * @return the owner of the Workflow
- */
- Principal getOwner();
-
- /**
* Identifies the next Step for a particular Outcome; if there is no next Step for this Outcome, this method returns <code>null</code>.
*
* @param outcome the outcome
@@ -196,17 +183,11 @@
Step getSuccessor( Outcome outcome );
/**
- * Gets the Workflow that is the parent of this Step.
- *
- * @return the workflow
- */
- Workflow getWorkflow();
-
- /**
* Sets the parent Workflow post-construction. Should be called after building a {@link Step}.
*
- * @param workflow the parent workflow to set
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
*/
- void setWorkflow( Workflow workflow );
+ void setWorkflow( final int workflowId, final Map< String, Object > workflowContext );
}
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Task.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Task.java
index dd88086..5e560ee 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Task.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Task.java
@@ -19,93 +19,77 @@
package org.apache.wiki.workflow;
import java.security.Principal;
+import java.util.Map;
+
/**
- * AbstractStep subclass that executes instructions, uninterrupted, and results
- * in an Outcome. Concrete classes only need to implement {@link Task#execute()}.
- * When the execution step completes, <code>execute</code> must return
- * {@link Outcome#STEP_COMPLETE}, {@link Outcome#STEP_CONTINUE} or
- * {@link Outcome#STEP_ABORT}. Subclasses can add any errors by calling the
- * helper method {@link AbstractStep#addError(String)}. The execute method should
- * <em>generally</em> capture and add errors to the error list instead of
+ * AbstractStep subclass that executes instructions, uninterrupted, and results in an Outcome. Concrete classes only need to implement
+ * {@link Task#execute()}. When the execution step completes, <code>execute</code> must return {@link Outcome#STEP_COMPLETE},
+ * {@link Outcome#STEP_CONTINUE} or {@link Outcome#STEP_ABORT}. Subclasses can add any errors by calling the helper method
+ * {@link AbstractStep#addError(String)}. The execute method should <em>generally</em> capture and add errors to the error list instead of
* throwing a WikiException.
* <p>
*
* @since 2.5
*/
-public abstract class Task extends AbstractStep
-{
+public abstract class Task extends AbstractStep {
+
private static final long serialVersionUID = 4630293957752430807L;
-
+
private Step m_successor = null;
/**
- * Protected constructor that creates a new Task with a specified message key.
- * After construction, the protected method {@link #setWorkflow(Workflow)} should be
- * called.
+ * Public constructor that creates a new Task with a specified message key. After construction, the protected method
+ * {@link #setWorkflow(int, Map)} should be called.
*
- * @param messageKey
- * the Step's message key, such as
- * <code>decision.editPageApproval</code>. By convention, the
- * message prefix should be a lower-case version of the Step's
- * type, plus a period (<em>e.g.</em>, <code>task.</code>
- * and <code>decision.</code>).
+ * @param messageKey the Step's message key, such as <code>decision.editPageApproval</code>. By convention, the message prefix should be
+ * a lower-case version of the Step's type, plus a period (<em>e.g.</em>, <code>task.</code> and <code>decision.</code>).
*/
- public Task( String messageKey )
- {
+ public Task( final String messageKey ) {
super( messageKey );
super.addSuccessor( Outcome.STEP_COMPLETE, null );
super.addSuccessor( Outcome.STEP_ABORT, null );
}
/**
- * Constructs a new instance of a Task, with an associated Workflow and
- * message key.
+ * Constructs a new instance of a Task, with an associated Workflow and message key.
*
- * @param workflow
- * the associated workflow
- * @param messageKey
- * the i18n message key
+ * @param workflowId the parent workflow id to set
+ * @param workflowContext the parent workflow context to set
+ * @param messageKey the i18n message key
*/
- public Task( Workflow workflow, String messageKey )
- {
+ public Task( final int workflowId, final Map< String, Object > workflowContext, final String messageKey ) {
this( messageKey );
- setWorkflow( workflow );
+ setWorkflow( workflowId, workflowContext );
}
/**
* Returns {@link SystemPrincipal#SYSTEM_USER}.
+ *
* @return the system principal
*/
- public final Principal getActor()
- {
+ public final Principal getActor() {
return SystemPrincipal.SYSTEM_USER;
}
/**
- * Sets the successor Step to this one, which will be triggered if the Task
- * completes successfully (that is, {@link Step#getOutcome()} returns
- * {@link Outcome#STEP_COMPLETE}. This method is really a convenient
- * shortcut for {@link Step#addSuccessor(Outcome, Step)}, where the first
- * parameter is {@link Outcome#STEP_COMPLETE}.
+ * Sets the successor Step to this one, which will be triggered if the Task completes successfully (that is, {@link Step#getOutcome()}
+ * returns {@link Outcome#STEP_COMPLETE}. This method is really a convenient shortcut for {@link Step#addSuccessor(Outcome, Step)},
+ * where the first parameter is {@link Outcome#STEP_COMPLETE}.
*
- * @param step
- * the successor
+ * @param step the successor
*/
- public final synchronized void setSuccessor( Step step )
- {
+ public final synchronized void setSuccessor( final Step step ) {
m_successor = step;
}
/**
- * Identifies the next Step after this Task finishes successfully. This
- * method will always return the value set in method
+ * Identifies the next Step after this Task finishes successfully. This method will always return the value set in method
* {@link #setSuccessor(Step)}, regardless of the current completion state.
*
* @return the next step
*/
- public final synchronized Step getSuccessor()
- {
+ public final synchronized Step getSuccessor() {
return m_successor;
}
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Workflow.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Workflow.java
index 7657b27..42c6c2f 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/Workflow.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/Workflow.java
@@ -30,6 +30,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -164,6 +165,8 @@
private static final long serialVersionUID = 5228149040690660032L;
+ private static final AtomicInteger idsCounter = new AtomicInteger( 1 );
+
/** ID value: the workflow ID has not been set. */
public static final int ID_NOT_SET = 0;
@@ -217,12 +220,13 @@
m_attributes = new ConcurrentHashMap<>();
m_currentStep = null;
m_history = new LinkedList<>();
- m_id = ID_NOT_SET;
+ m_id = idsCounter.getAndIncrement();
m_key = messageKey;
m_messageArgs = new ArrayList<>();
m_owner = owner;
m_started = false;
m_state = CREATED;
+ WorkflowEventEmitter.fireEvent( this, WorkflowEvent.CREATED );
}
/**
@@ -243,7 +247,7 @@
if( m_currentStep != null ) {
if( m_currentStep instanceof Decision ) {
- WorkflowEventEmitter.fireEvent( ( Decision )m_currentStep, WorkflowEvent.DQ_REMOVAL );
+ WorkflowEventEmitter.fireEvent( m_currentStep, WorkflowEvent.DQ_REMOVAL );
}
m_currentStep.setOutcome( Outcome.STEP_ABORT );
m_history.addLast( m_currentStep );
@@ -313,6 +317,15 @@
}
/**
+ * Retrieves workflow's attributes.
+ *
+ * @return workflow's attributes.
+ */
+ public final Map< String, Object > getAttributes() {
+ return m_attributes;
+ }
+
+ /**
* The end time for this Workflow, expressed as a system time number. This value is equal to the end-time value returned by the final
* Step's {@link Step#getEndTime()} method, if the workflow has completed. Otherwise, this method returns {@link Step#TIME_NOT_SET}.
*
@@ -461,6 +474,7 @@
if( m_state != WAITING ) {
throw new IllegalStateException( "Workflow is not paused; cannot restart." );
}
+ WorkflowEventEmitter.fireEvent( this, WorkflowEvent.STARTED );
m_state = RUNNING;
WorkflowEventEmitter.fireEvent( this, WorkflowEvent.RUNNING );
@@ -522,10 +536,11 @@
if( m_started ) {
throw new IllegalStateException( "Workflow has already started." );
}
+ WorkflowEventEmitter.fireEvent( this, WorkflowEvent.STARTED );
m_started = true;
m_state = RUNNING;
- WorkflowEventEmitter.fireEvent( this, WorkflowEvent.RUNNING );
+ WorkflowEventEmitter.fireEvent( this, WorkflowEvent.RUNNING );
// Mark the first step as the current one & add to history
m_currentStep = m_firstStep;
m_history.add( m_currentStep );
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowBuilder.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowBuilder.java
index 9a8e7f2..b497147 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowBuilder.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowBuilder.java
@@ -117,7 +117,7 @@
if ( decisionRequired ) {
// Look up the name of the approver (user or group) listed in jspwiki.properties; approvals go to the approver's decision queue
final Principal approverPrincipal = mgr.getApprover( workflowApproverKey );
- final Decision decision = new SimpleDecision( workflow, decisionKey, approverPrincipal );
+ final Decision decision = new SimpleDecision( workflow.getId(), workflow.getAttributes(), decisionKey, approverPrincipal );
// Add facts to the Decision, if any were supplied
if( facts != null ) {
@@ -132,7 +132,7 @@
// If rejected, sent a notification
if ( rejectedMessageKey != null ) {
- final SimpleNotification rejectNotification = new SimpleNotification( workflow, rejectedMessageKey, submitter );
+ final SimpleNotification rejectNotification = new SimpleNotification( workflow.getId(), workflow.getAttributes(), rejectedMessageKey, submitter );
decision.addSuccessor( Outcome.DECISION_DENY, rejectNotification );
}
@@ -158,9 +158,9 @@
// Make sure our tasks have this workflow as the parent, then return
if( prepTask != null ) {
- prepTask.setWorkflow( workflow );
+ prepTask.setWorkflow( workflow.getId(), workflow.getAttributes() );
}
- completionTask.setWorkflow( workflow );
+ completionTask.setWorkflow( workflow.getId(), workflow.getAttributes() );
return workflow;
}
diff --git a/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowEventEmitter.java b/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowEventEmitter.java
index 8c2f899..8ecabd5 100644
--- a/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowEventEmitter.java
+++ b/jspwiki-main/src/main/java/org/apache/wiki/workflow/WorkflowEventEmitter.java
@@ -18,9 +18,12 @@
*/
package org.apache.wiki.workflow;
+import org.apache.wiki.event.WikiEventListener;
import org.apache.wiki.event.WikiEventManager;
import org.apache.wiki.event.WorkflowEvent;
+import java.util.Set;
+
/**
* Emits all kind of {@link WorkflowEvent}s.
@@ -39,4 +42,14 @@
}
}
+ public static void registerListener( final WikiEventListener listener ) {
+ if ( WikiEventManager.isListening( get() ) ) {
+ final Set< WikiEventListener > attachedListeners = WikiEventManager.getWikiEventListeners( get() );
+ attachedListeners.stream()
+ .filter( l -> listener.getClass().isAssignableFrom( l.getClass() ) )
+ .forEach( WikiEventManager::removeWikiEventListener );
+ }
+ WikiEventManager.addWikiEventListener( WorkflowEventEmitter.get(), listener );
+ }
+
}
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/auth/UserManagerTest.java b/jspwiki-main/src/test/java/org/apache/wiki/auth/UserManagerTest.java
index 7565109..aecf7de 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/auth/UserManagerTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/auth/UserManagerTest.java
@@ -326,7 +326,7 @@
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_LOGIN_NAME, profile.getLoginName() ), facts.get( 1 ) );
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_SUBMITTER, session.getUserPrincipal().getName() ), facts.get( 2 ) );
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_EMAIL, profile.getEmail() ), facts.get( 3 ) );
- Assertions.assertEquals( profile, d.getWorkflow().getAttribute( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE ) );
+ Assertions.assertEquals( profile, d.getWorkflowContext().get( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE ) );
// Approve the profile
d.decide( Outcome.DECISION_APPROVE );
@@ -377,7 +377,7 @@
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_LOGIN_NAME, profile.getLoginName() ), facts.get( 1 ) );
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_SUBMITTER, session.getUserPrincipal().getName() ), facts.get( 2 ) );
Assertions.assertEquals( new Fact( WorkflowManager.WF_UP_CREATE_SAVE_FACT_PREFS_EMAIL, profile.getEmail() ), facts.get( 3 ) );
- Assertions.assertEquals( profile, d.getWorkflow().getAttribute( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE ) );
+ Assertions.assertEquals( profile, d.getWorkflowContext().get( WorkflowManager.WF_UP_CREATE_SAVE_ATTR_SAVED_PROFILE ) );
// Approve the profile
d.decide( Outcome.DECISION_DENY );
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/ApprovalWorkflowTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/ApprovalWorkflowTest.java
index 7f25b9e..ba05915 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/ApprovalWorkflowTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/ApprovalWorkflowTest.java
@@ -28,36 +28,22 @@
import org.apache.wiki.filters.FilterManager;
import org.apache.wiki.pages.PageManager;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.security.Principal;
import java.util.Collection;
import java.util.List;
-import java.util.Properties;
+
+import static org.apache.wiki.TestEngine.with;
+
public class ApprovalWorkflowTest {
- WorkflowBuilder m_builder;
- TestEngine m_engine;
- WorkflowManager m_wm;
- DecisionQueue m_dq;
-
- @BeforeEach
- public void setUp() throws Exception {
- final Properties props = TestEngine.getTestProperties();
-
- // Explicitly turn on Admin approvals for page saves and our sample approval workflow
- props.put("jspwiki.approver.workflow.saveWikiPage", "Admin");
- props.put( "jspwiki.approver.workflow.approvalWorkflow", Users.JANNE );
-
- // Start the wiki engine
- m_engine = new TestEngine( props );
- m_wm = m_engine.getManager( WorkflowManager.class );
- m_dq = m_wm.getDecisionQueue();
- m_builder = WorkflowBuilder.getBuilder( m_engine );
- }
-
+ static TestEngine m_engine = TestEngine.build( with( "jspwiki.approver.workflow.saveWikiPage", "Admin" ),
+ with( "jspwiki.approver.workflow.approvalWorkflow", Users.JANNE ) );
+ static WorkflowManager m_wm = m_engine.getManager( WorkflowManager.class );
+ static DecisionQueue m_dq = m_wm.getDecisionQueue();
+ static WorkflowBuilder m_builder = WorkflowBuilder.getBuilder( m_engine );
@Test
public void testBuildApprovalWorkflow() throws WikiException {
@@ -66,15 +52,15 @@
final Task prepTask = new TestPrepTask( "task.preSaveWikiPage" );
final String decisionKey = "decision.saveWikiPage";
final Fact[] facts = new Fact[3];
- facts[0] = new Fact("fact1", 1 );
- facts[1] = new Fact("fact2","A factual String");
- facts[2] = new Fact("fact3",Outcome.DECISION_ACKNOWLEDGE);
+ facts[ 0 ] = new Fact( "fact1", 1 );
+ facts[ 1 ] = new Fact( "fact2", "A factual String" );
+ facts[ 2 ] = new Fact( "fact3", Outcome.DECISION_ACKNOWLEDGE );
final Task completionTask = new TestPrepTask( "task.saveWikiPage" );
final String rejectedMessageKey = "notification.saveWikiPage.reject";
- final Workflow w = m_builder.buildApprovalWorkflow(submitter, workflowApproverKey,
- prepTask, decisionKey, facts,
- completionTask, rejectedMessageKey);
+ final Workflow w = m_builder.buildApprovalWorkflow( submitter, workflowApproverKey,
+ prepTask, decisionKey, facts,
+ completionTask, rejectedMessageKey );
// Check to see if the workflow built correctly
Assertions.assertFalse( w.isStarted() || w.isCompleted() || w.isAborted() );
@@ -137,10 +123,10 @@
final String workflowApproverKey = "workflow.approvalWorkflow";
final Task prepTask = new TestPrepTask( "task.preSaveWikiPage" );
final String decisionKey = "decision.saveWikiPage";
- final Fact[] facts = new Fact[3];
- facts[0] = new Fact("fact1", 1 );
- facts[1] = new Fact("fact2","A factual String");
- facts[2] = new Fact("fact3",Outcome.DECISION_ACKNOWLEDGE);
+ final Fact[] facts = new Fact[ 3 ];
+ facts[ 0 ] = new Fact( "fact1", 1 );
+ facts[ 1 ] = new Fact( "fact2", "A factual String" );
+ facts[ 2 ] = new Fact( "fact3", Outcome.DECISION_ACKNOWLEDGE );
final Task completionTask = new TestPrepTask( "task.saveWikiPage" );
final String rejectedMessageKey = "notification.saveWikiPage.reject";
@@ -177,25 +163,23 @@
// Create a sample test page and try to save it
final String pageName = "SaveWikiPageWorkflow-Test" + System.currentTimeMillis();
final String text = "This is a test!";
- try {
- m_engine.saveTextAsJanne( pageName, text );
- } catch( final DecisionRequiredException e ) {
- // Swallow exception, because it is expected...
- }
+
+ // Expected exception...
+ Assertions.assertThrows( DecisionRequiredException.class, () -> m_engine.saveTextAsJanne( pageName, text ) );
// How do we know the workflow works? Well, first of all the page shouldn't exist yet...
- Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists(pageName));
+ Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists( pageName ) );
// Second, GroupPrincipal Admin should see a Decision in its queue
Collection< Decision > decisions = m_dq.getActorDecisions( m_engine.adminSession() );
- Assertions.assertEquals(1, decisions.size());
+ Assertions.assertEquals( 1, decisions.size() );
// Now, approve the decision and it should go away, and page should appear.
final Decision decision = decisions.iterator().next();
- decision.decide(Outcome.DECISION_APPROVE);
- Assertions.assertTrue( m_engine.getManager( PageManager.class ).wikiPageExists(pageName));
+ decision.decide( Outcome.DECISION_APPROVE );
+ Assertions.assertTrue( m_engine.getManager( PageManager.class ).wikiPageExists( pageName ) );
decisions = m_dq.getActorDecisions( m_engine.adminSession() );
- Assertions.assertEquals(0, decisions.size());
+ Assertions.assertEquals( 0, decisions.size() );
// Delete the page we created
m_engine.getManager( PageManager.class ).deletePage( pageName );
@@ -213,27 +197,27 @@
}
// How do we know the workflow works? Well, first of all the page shouldn't exist yet...
- Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists(pageName));
+ Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists( pageName ) );
// ...and there should be a Decision in GroupPrincipal Admin's queue
Collection< Decision > decisions = m_dq.getActorDecisions( m_engine.adminSession() );
- Assertions.assertEquals(1, decisions.size());
+ Assertions.assertEquals( 1, decisions.size() );
// Now, DENY the decision and the page should still not exist...
Decision decision = decisions.iterator().next();
- decision.decide(Outcome.DECISION_DENY);
- Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists(pageName) );
+ decision.decide( Outcome.DECISION_DENY );
+ Assertions.assertFalse( m_engine.getManager( PageManager.class ).wikiPageExists( pageName ) );
// ...but there should also be a notification decision in Janne's queue
decisions = m_dq.getActorDecisions( m_engine.janneSession() );
- Assertions.assertEquals(1, decisions.size());
+ Assertions.assertEquals( 1, decisions.size() );
decision = decisions.iterator().next();
- Assertions.assertEquals(WorkflowManager.WF_WP_SAVE_REJECT_MESSAGE_KEY, decision.getMessageKey());
+ Assertions.assertEquals( WorkflowManager.WF_WP_SAVE_REJECT_MESSAGE_KEY, decision.getMessageKey() );
// Once Janne disposes of the notification, his queue should be empty
- decision.decide(Outcome.DECISION_ACKNOWLEDGE);
+ decision.decide( Outcome.DECISION_ACKNOWLEDGE );
decisions = m_dq.getActorDecisions( m_engine.janneSession() );
- Assertions.assertEquals(0, decisions.size());
+ Assertions.assertEquals( 0, decisions.size() );
}
@Test
@@ -245,12 +229,9 @@
// Create a sample test page and try to save it
final String pageName = "SaveWikiPageWorkflow-Test" + System.currentTimeMillis();
final String text = "This is a test!";
- try
- {
+ try {
m_engine.saveTextAsJanne(pageName, text);
- }
- catch ( final WikiException e )
- {
+ } catch( final WikiException e ) {
Assertions.assertTrue( e instanceof FilterException );
Assertions.assertEquals( "Page save aborted.", e.getMessage() );
return;
@@ -262,8 +243,8 @@
* Sample "prep task" that sets an attribute in the workflow indicating
* that it ran successfully,
*/
- public static class TestPrepTask extends Task
- {
+ public static class TestPrepTask extends Task {
+
private static final long serialVersionUID = 1L;
public TestPrepTask( final String messageKey )
@@ -273,7 +254,7 @@
@Override
public Outcome execute() {
- getWorkflow().setAttribute( getMessageKey(), "Completed" );
+ getWorkflowContext().put( getMessageKey(), "Completed" );
setOutcome( Outcome.STEP_COMPLETE );
return Outcome.STEP_COMPLETE;
}
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/DecisionQueueTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/DecisionQueueTest.java
index 9ac1201..fdcf1f9 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/DecisionQueueTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/DecisionQueueTest.java
@@ -54,12 +54,12 @@
adminSession = m_engine.adminSession();
janneSession = m_engine.janneSession();
w = new Workflow("workflow.key", new WikiPrincipal("Owner1"));
- d1 = new SimpleDecision(w, "decision1.key", new GroupPrincipal("Admin"));
- d2 = new SimpleDecision(w, "decision2.key", new WikiPrincipal("Owner2"));
- d3 = new SimpleDecision(w, "decision3.key", janneSession.getUserPrincipal());
- m_queue.add(d1);
- m_queue.add(d2);
- m_queue.add(d3);
+ d1 = new SimpleDecision( w.getId(), w.getAttributes(), "decision1.key", new GroupPrincipal( "Admin" ) );
+ d2 = new SimpleDecision( w.getId(), w.getAttributes(), "decision2.key", new WikiPrincipal( "Owner2" ) );
+ d3 = new SimpleDecision( w.getId(), w.getAttributes(), "decision3.key", janneSession.getUserPrincipal() );
+ m_queue.add( d1 );
+ m_queue.add( d2 );
+ m_queue.add( d3 );
}
@Test
@@ -150,38 +150,37 @@
}
@Test
- public void testDecisionWorkflow() throws WikiException
- {
+ public void testDecisionWorkflow() throws WikiException {
final Principal janne = janneSession.getUserPrincipal();
// Clean out the queue first
- m_queue.remove(d1);
- m_queue.remove(d2);
- m_queue.remove(d3);
+ m_queue.remove( d1 );
+ m_queue.remove( d2 );
+ m_queue.remove( d3 );
// Create a workflow with 3 steps, with a Decision for Janne in the middle
- w = new Workflow("workflow.key", new WikiPrincipal("Owner1"));
- final Step startTask = new TaskTest.NormalTask(w);
- final Step endTask = new TaskTest.NormalTask(w);
- final Decision decision = new SimpleDecision(w, "decision.Actor1Decision", janne);
- startTask.addSuccessor(Outcome.STEP_COMPLETE, decision);
- decision.addSuccessor(Outcome.DECISION_APPROVE, endTask);
- w.setFirstStep(startTask);
+ w = new Workflow( "workflow.key", new WikiPrincipal( "Owner1" ) );
+ final Step startTask = new TaskTest.NormalTask( w );
+ final Step endTask = new TaskTest.NormalTask( w );
+ final Decision decision = new SimpleDecision( w.getId(), w.getAttributes(), "decision.Actor1Decision", janne );
+ startTask.addSuccessor( Outcome.STEP_COMPLETE, decision );
+ decision.addSuccessor( Outcome.DECISION_APPROVE, endTask );
+ w.setFirstStep( startTask );
// Start the workflow, and verify that the Decision is the current Step
w.start();
- Assertions.assertEquals(decision, w.getCurrentStep());
+ Assertions.assertEquals( decision, w.getCurrentStep() );
// Verify that it's also in Janne's DecisionQueue
- Collection< Decision > decisions = m_queue.getActorDecisions(janneSession);
- Assertions.assertEquals(1, decisions.size());
- final Decision d = (Decision)decisions.iterator().next();
- Assertions.assertEquals(decision, d);
+ Collection< Decision > decisions = m_queue.getActorDecisions( janneSession );
+ Assertions.assertEquals( 1, decisions.size() );
+ final Decision d = ( Decision )decisions.iterator().next();
+ Assertions.assertEquals( decision, d );
// Make Decision, and verify that it's gone from the queue
- m_queue.decide(decision, Outcome.DECISION_APPROVE);
- decisions = m_queue.getActorDecisions(janneSession);
- Assertions.assertEquals(0, decisions.size());
+ m_queue.decide( decision, Outcome.DECISION_APPROVE );
+ decisions = m_queue.getActorDecisions( janneSession );
+ Assertions.assertEquals( 0, decisions.size() );
}
}
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/SimpleDecisionTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/SimpleDecisionTest.java
index 5bf3539..6cd4e86 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/SimpleDecisionTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/SimpleDecisionTest.java
@@ -36,7 +36,7 @@
@BeforeEach
public void setUp() throws Exception {
m_workflow = new Workflow( "workflow.key", new WikiPrincipal( "Owner1" ) );
- m_decision = new SimpleDecision( m_workflow, "decision.key", new WikiPrincipal( "Actor1" ) );
+ m_decision = new SimpleDecision( m_workflow.getId(), m_workflow.getAttributes(), "decision.key", new WikiPrincipal( "Actor1" ) );
}
@Test
@@ -79,11 +79,11 @@
@Test
public void testSuccessors() {
// If the decision is approved, branch to another decision (d2)
- final Step d2 = new SimpleDecision( m_workflow, "decision2.key", new WikiPrincipal( "Actor1" ) );
+ final Step d2 = new SimpleDecision( m_workflow.getId(), m_workflow.getAttributes(), "decision2.key", new WikiPrincipal( "Actor1" ) );
m_decision.addSuccessor( Outcome.DECISION_APPROVE, d2 );
// If the decision is denied, branch to another decision (d3)
- final Step d3 = new SimpleDecision( m_workflow, "decision3.key", new WikiPrincipal( "Actor1" ) );
+ final Step d3 = new SimpleDecision( m_workflow.getId(), m_workflow.getAttributes(), "decision3.key", new WikiPrincipal( "Actor1" ) );
m_decision.addSuccessor( Outcome.DECISION_DENY, d3 );
Assertions.assertEquals( d2, m_decision.getSuccessor( Outcome.DECISION_APPROVE ) );
@@ -148,7 +148,7 @@
@Test
public void testGetWorkflow() {
- Assertions.assertEquals( m_workflow, m_decision.getWorkflow() );
+ Assertions.assertEquals( m_workflow.getId(), m_decision.getWorkflowId() );
}
@Test
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/TaskTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/TaskTest.java
index 6e330c0..53612e9 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/TaskTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/TaskTest.java
@@ -40,7 +40,7 @@
public NormalTask( final Workflow workflow)
{
- super(workflow, "task.normal");
+ super(workflow.getId(), workflow.getAttributes(), "task.normal");
}
public Outcome execute() throws WikiException
{
@@ -56,7 +56,7 @@
public ErrorTask( final Workflow workflow)
{
- super(workflow, "task.error");
+ super(workflow.getId(), workflow.getAttributes(), "task.error");
}
public Outcome execute() throws WikiException
{
@@ -86,11 +86,11 @@
public void testSuccessors()
{
// If task finishes normally, branch to a decision (d1)
- final Step d1 = new SimpleDecision(m_workflow, "decision1.key", new WikiPrincipal("Actor1"));
+ final Step d1 = new SimpleDecision(m_workflow.getId(), m_workflow.getAttributes(), "decision1.key", new WikiPrincipal("Actor1"));
m_task.addSuccessor(Outcome.STEP_COMPLETE, d1);
// If the task aborts, branch to an alternate decision (d2)
- final Step d2 = new SimpleDecision(m_workflow, "decision2.key", new WikiPrincipal("Actor2"));
+ final Step d2 = new SimpleDecision(m_workflow.getId(), m_workflow.getAttributes(), "decision2.key", new WikiPrincipal("Actor2"));
m_task.addSuccessor(Outcome.STEP_ABORT, d2);
Assertions.assertEquals(d1, m_task.getSuccessor(Outcome.STEP_COMPLETE));
@@ -171,7 +171,7 @@
@Test
public void testGetWorkflow()
{
- Assertions.assertEquals(m_workflow, m_task.getWorkflow());
+ Assertions.assertEquals(m_workflow.getId(), m_task.getWorkflowId() );
}
@Test
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowManagerTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowManagerTest.java
index 2597ca9..8975859 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowManagerTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowManagerTest.java
@@ -41,7 +41,7 @@
w = new Workflow( "workflow.key", new WikiPrincipal( "Owner1" ) );
final Step startTask = new TaskTest.NormalTask( w );
final Step endTask = new TaskTest.NormalTask( w );
- final Decision decision = new SimpleDecision( w, "decision.editWikiApproval", new WikiPrincipal( "Actor1" ) );
+ final Decision decision = new SimpleDecision( w.getId(), w.getAttributes(), "decision.editWikiApproval", new WikiPrincipal( "Actor1" ) );
startTask.addSuccessor( Outcome.STEP_COMPLETE, decision );
decision.addSuccessor( Outcome.DECISION_APPROVE, endTask );
w.setFirstStep( startTask );
@@ -52,9 +52,7 @@
@Test
public void testStart() throws WikiException {
- // Once we start the workflow, it should show that it's started
- // and the WM should have assigned it an ID
- Assertions.assertEquals( Workflow.ID_NOT_SET, w.getId() );
+ // Once we start the workflow, it should show that it's started and the WM should have assigned it an ID
Assertions.assertFalse( w.isStarted() );
wm.start( w );
Assertions.assertNotEquals( Workflow.ID_NOT_SET, w.getId() );
@@ -63,17 +61,16 @@
@Test
public void testWorkflows() throws WikiException {
- // There should be no workflows in the cache, and none in completed list
- Assertions.assertEquals( 0, wm.getWorkflows().size() );
+ // After Workflow being created, it gets added to the workflows cache, there should be none in the completed list
+ Assertions.assertEquals( 1, wm.getWorkflows().size() );
Assertions.assertEquals( 0, wm.getCompletedWorkflows().size() );
- // After starting, there should be 1 in the cache, with ID=1
+ // After starting, there should be 1 in the cache
wm.start( w );
Assertions.assertEquals( 1, wm.getWorkflows().size() );
Assertions.assertEquals( 0, wm.getCompletedWorkflows().size() );
final Workflow workflow = wm.getWorkflows().iterator().next();
Assertions.assertEquals( w, workflow );
- Assertions.assertEquals( 1, workflow.getId() );
// After forcing a decision on step 2, the workflow should complete and vanish from the cache
final Decision d = ( Decision )w.getCurrentStep();
diff --git a/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowTest.java b/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowTest.java
index 84b7444..6064c28 100644
--- a/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowTest.java
+++ b/jspwiki-main/src/test/java/org/apache/wiki/workflow/WorkflowTest.java
@@ -32,6 +32,8 @@
public class WorkflowTest {
+ WorkflowManager workflowsEventListener;
+
Workflow w;
Task initTask;
@@ -44,6 +46,9 @@
@BeforeEach
public void setUp() throws Exception {
+ // listen to workflow events
+ workflowsEventListener = new DefaultWorkflowManager();
+
// Create workflow; owner is test user
w = new Workflow( "workflow.myworkflow", new WikiPrincipal( "Owner1" ) );
@@ -55,7 +60,7 @@
// Create an intermetidate decision step
final Principal actor = new GroupPrincipal( "Admin" );
- decision = new SimpleDecision( w, "decision.AdminDecision", actor );
+ decision = new SimpleDecision( w.getId(), w.getAttributes(), "decision.AdminDecision", actor );
// Hook the steps together
initTask.addSuccessor( Outcome.STEP_COMPLETE, decision );
@@ -74,7 +79,6 @@
Assertions.assertNull( w.getCurrentStep() );
Assertions.assertNull( w.getCurrentActor() );
Assertions.assertEquals( 0, w.getHistory().size() );
- Assertions.assertEquals( Workflow.ID_NOT_SET, w.getId() );
Assertions.assertEquals( new WikiPrincipal( "Owner1" ), w.getOwner() );
Assertions.assertEquals( Workflow.CREATED, w.getCurrentState() );
Assertions.assertEquals( Step.TIME_NOT_SET, w.getStartTime() );
@@ -355,7 +359,6 @@
@Test
public void testSetId() {
- Assertions.assertEquals( Workflow.ID_NOT_SET, w.getId() );
w.setId( 1001 );
Assertions.assertEquals( 1001, w.getId() );
}