📄 workflow.java
字号:
/** * <p> * Returns an array of message arguments, used by * {@link java.text.MessageFormat} to create localized messages. The first * two array elements will always be these: * </p> * <ul> * <li>String representing the name of the workflow owner (<em>i.e.</em>,{@link #getOwner()})</li> * <li>String representing the name of the current actor (<em>i.e.</em>,{@link #getCurrentActor()}). * If the current step is <code>null</code> because the workflow hasn't started or has already * finished, the value of this argument will be a dash character (<code>-</code>)</li> * </ul> * <p> * Workflow and Step subclasses are free to append items to this collection * with {@link #addMessageArgument(Serializable)}. * </p> * * @return the array of message arguments */ public final Serializable[] getMessageArguments() { List<Serializable> args = new ArrayList<Serializable>(); args.add( m_owner.getName() ); Principal actor = getCurrentActor(); args.add( actor == null ? "-" : actor.getName() ); args.addAll( m_messageArgs ); return args.toArray( new Serializable[args.size()] ); } /** * Returns an i18n message key for the name of this workflow; for example, * <code>workflow.saveWikiPage</code>. * * @return the name */ public final String getMessageKey() { return m_key; } /** * The owner Principal on whose behalf this Workflow is being executed; that * is, the user who created the workflow. * * @return the name of the Principal who owns this workflow */ public final Principal getOwner() { return m_owner; } /** * The start time for this Workflow, expressed as a system time number. This * value is equal to the start-time value returned by the first Step's * {@link Step#getStartTime()} method, if the workflow has started already. * Otherwise, this method returns {@link #TIME_NOT_SET}. * * @return the start time */ public final Date getStartTime() { return isStarted() ? m_firstStep.getStartTime() : TIME_NOT_SET; } /** * Returns the WorkflowManager that contains this Workflow. * * @return the workflow manager */ public final synchronized WorkflowManager getWorkflowManager() { return m_manager; } /** * Returns a Step history for this Workflow as a List, chronologically, from the * first Step to the currently executing one. The first step is the first * item in the array. If the Workflow has not started, this method returns a * zero-length array. * * @return an array of Steps representing those that have executed, or are * currently executing */ public final List getHistory() { return Collections.unmodifiableList( m_history ); } /** * Returns <code>true</code> if the workflow had been previously aborted. * * @return the result */ public final boolean isAborted() { return m_state == ABORTED; } /** * Determines whether this Workflow is completed; that is, if it has no * additional Steps to perform. If the last Step in the workflow is * finished, this method will return <code>true</code>. * * @return <code>true</code> if the workflow has been started but has no * more steps to perform; <code>false</code> if not. */ public final synchronized boolean isCompleted() { // If current step is null, then we're done return m_started && m_state == COMPLETED; } /** * Determines whether this Workflow has started; that is, its * {@link #start()} method has been executed. * * @return <code>true</code> if the workflow has been started; * <code>false</code> if not. */ public final boolean isStarted() { return m_started; } /** * Convenience method that returns the predecessor of the current Step. This * method simply examines the Workflow history and returns the * second-to-last Step. * * @return the predecessor, or <code>null</code> if the first Step is * currently executing */ public final Step getPreviousStep() { return previousStep( m_currentStep ); } /** * Restarts the Workflow from the {@link #WAITING} state and puts it into * the {@link #RUNNING} state again. If the Workflow had not previously been * paused, this method throws an IllegalStateException. If any of the * Steps in this Workflow throw a WikiException, the Workflow will abort * and propagate the exception to callers. * @throws WikiException if the current task's {@link Task#execute()} method * throws an exception */ public final synchronized void restart() throws WikiException { if ( m_state != WAITING ) { throw new IllegalStateException( "Workflow is not paused; cannot restart." ); } m_state = RUNNING; fireEvent( WorkflowEvent.RUNNING ); // Process current step try { processCurrentStep(); } catch ( WikiException e ) { abort(); throw e; } } /** * Temporarily associates an object with this Workflow, as a named attribute, for the * duration of workflow execution. The passed object can be anything required by * an executing Step, although it <em>should</em> be serializable. Note that when the workflow * completes or aborts, all attributes will be cleared. * * @param attr * the attribute name * @param obj * the value */ public final synchronized void setAttribute(String attr, Object obj ) { if ( m_attributes == null ) { m_attributes = new HashMap<String, Object>(); } m_attributes.put( attr, obj ); } /** * Sets the first Step for this Workflow, which will be executed immediately * after the {@link #start()} method executes. Note than the Step is not * marked as the "current" step or added to the Workflow history until the * {@link #start()} method is called. * * @param step * the first step for the workflow */ public final synchronized void setFirstStep(Step step) { m_firstStep = step; } /** * Sets the unique identifier for this Workflow. * * @param id * the unique identifier */ public final synchronized void setId( int id ) { this.m_id = id; } /** * Sets the WorkflowManager that contains this Workflow. * * @param manager * the workflow manager */ public final synchronized void setWorkflowManager( WorkflowManager manager ) { m_manager = manager; addWikiEventListener( manager ); } /** * Starts the Workflow and sets the state to {@link #RUNNING}. If the * Workflow has already been started (or previously aborted), this method * returns an {@linkplain IllegalStateException}. If any of the * Steps in this Workflow throw a WikiException, the Workflow will abort * and propagate the exception to callers. * @throws WikiException if the current Step's {@link Step#start()} * method throws an exception of any kind */ public final synchronized void start() throws WikiException { if ( m_state == ABORTED ) { throw new IllegalStateException( "Workflow cannot be started; it has already been aborted." ); } if ( m_started ) { throw new IllegalStateException( "Workflow has already started." ); } m_started = true; m_state = RUNNING; fireEvent( WorkflowEvent.RUNNING ); // Mark the first step as the current one & add to history m_currentStep = m_firstStep; m_history.add( m_currentStep ); // Process current step try { processCurrentStep(); } catch ( WikiException e ) { abort(); throw e; } } /** * Sets the Workflow in the {@link #WAITING} state. If the Workflow is not * running or has already been paused, this method throws an * IllegalStateException. Once paused, the Workflow can be un-paused by * executing the {@link #restart()} method. */ public final synchronized void waitstate() { if ( m_state != RUNNING ) { throw new IllegalStateException( "Workflow is not running; cannot pause." ); } m_state = WAITING; fireEvent( WorkflowEvent.WAITING ); } /** * Clears the attribute map and sets the current step field to * <code>null</code>. */ protected void cleanup() { m_currentStep = null; m_attributes = null; } /** * Protected helper method that changes the Workflow's state to * {@link #COMPLETED} and sets the current Step to <code>null</code>. It * calls the {@link #cleanup()} method to flush retained objects. * This method will no-op if it has previously been called. */ protected final synchronized void complete() { if ( !isCompleted() ) { m_state = COMPLETED; fireEvent( WorkflowEvent.COMPLETED ); cleanup(); } } /** * Protected method that returns the predecessor for a supplied Step. * * @param step * the Step for which the predecessor is requested * @return its predecessor, or <code>null</code> if the first Step was * supplied. */ protected final Step previousStep(Step step) { int index = m_history.indexOf( step ); return index < 1 ? null : m_history.get( index - 1 ); } /** * Protected method that processes the current Step by calling * {@link Step#execute()}. If the <code>execute</code> throws an * exception, this method will propagate the exception immediately * to callers without aborting. * @throws WikiException if the current Step's {@link Step#start()} * method throws an exception of any kind */ protected final void processCurrentStep() throws WikiException { while ( m_currentStep != null ) { // Start and execute the current step if ( !m_currentStep.isStarted() ) { m_currentStep.start(); } try { Outcome result = m_currentStep.execute(); if ( Outcome.STEP_ABORT.equals( result ) ) { abort(); break; } if ( !m_currentStep.isCompleted() ) { m_currentStep.setOutcome( result ); } } catch ( WikiException e ) { throw e; } // Get the execution Outcome; if not complete, pause workflow and // exit Outcome outcome = m_currentStep.getOutcome(); if ( !outcome.isCompletion() ) { waitstate(); break; } // Get the next Step; if null, we're done Step nextStep = m_currentStep.getSuccessor( outcome ); if ( nextStep == null ) { complete(); break; } // Add the next step to Workflow history, and mark as current m_history.add( nextStep ); m_currentStep = nextStep; } } // events processing ....................................................... /** * Registers a WikiEventListener with this instance. This is a convenience * method. * * @param listener * the event listener */ public final synchronized void addWikiEventListener( WikiEventListener listener ) { WikiEventManager.addWikiEventListener( this, listener ); } /** * Un-registers a WikiEventListener with this instance. This is a * convenience method. * * @param listener * the event listener */ public final synchronized void removeWikiEventListener( WikiEventListener listener ) { WikiEventManager.removeWikiEventListener( this, listener ); } /** * Fires a WorkflowEvent of the provided type to all registered listeners. * * @see com.ecyrd.jspwiki.event.WorkflowEvent * @param type * the event type to be fired */ protected final void fireEvent( int type ) { if ( WikiEventManager.isListening( this ) ) { WikiEventManager.fireEvent( this, new WorkflowEvent( this, type ) ); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -