    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019package org.apache.wiki.workflow;
    020
    021import org.apache.wiki.api.core.Context;
    022import org.apache.wiki.api.exceptions.WikiException;
    023
    024import java.io.Serializable;
    025import java.security.Principal;
    026import java.util.Collection;
    027import java.util.Date;
    028import java.util.List;
    029import java.util.Map;
    030
    031
    032/**
    033 * <p>
    034 * Discrete unit of work in a Workflow, such as a {@link Decision} or a {@link Task}. Decisions require user input, while Tasks do not.
    035 * All Steps, however, possess these properties:
    036 * </p>
    037 * <ul>
    038 * <li><strong>actor</strong>: the Principal responsible for executing the Step; returned by {@link Step#getActor()}.</li>
    039 * <li><strong>availableOutcomes</strong>: a collection of possible "outcomes," such as "approve decision" ({@link Outcome#DECISION_APPROVE}),
    040 * "reassign decision" ({@link Outcome#DECISION_REASSIGN}), "abort step" ({@link Outcome#STEP_ABORT}) and others. The range of possible
    041 * Outcomes for the Step is returned by {@link Step#getAvailableOutcomes()}; see the Outcome class for more details.</li>
    042 * <li><strong>errors</strong>: an collection of Strings indicating errors returned by the Step. These values are returned by
    043 * {@link Step#getErrors()}.</li>
    044 * <li><strong>started</strong> and <strong>completed</strong>: whether the Step has started/finished. These values are returned by
    045 * {@link Step#isStarted()} and {@link Step#isCompleted()}.</li>
    046 * <li><strong>startTime</strong> and <strong>endTime</strong>: the time when the Step started and finished. These values are returned by
    047 * {@link Step#getStartTime()} and {@link Step#getEndTime()}, respectively.</li>
    048 * <li><strong>workflow</strong>: the parent Workflow. </li>
    049 * </ul>
    050 * <p>
    051 * Steps contain a {@link #getMessageKey()} method that returns a key that can be used with the {@link org.apache.wiki.i18n.InternationalizationManager}.
    052 * See also {@link Workflow#getMessageArguments()}, which is a convenience method that returns message arguments.
    053 * </p>
    054 *
    055 * @since 2.5
    056 */
    057public interface Step extends Serializable {
    058
    059    /** Time value: the start or end time has not been set. */
    060    Date TIME_NOT_SET = new Date( 0 );
    061
    062    /**
    063     * Adds a successor Step to this one, which will be triggered by a supplied Outcome. Implementations should respect the order in which
    064     * Outcomes are added; {@link #getAvailableOutcomes()} should return them in the same order they were added.
    065     *
    066     * @param outcome the Outcome triggering a particular successor Step
    067     * @param step the Step to associated with this Outcomes (<code>null</code> denotes no Steps)
    068     */
    069    void addSuccessor( Outcome outcome, Step step );
    070
    071    /**
    072     * Returns a Collection of available outcomes, such as "approve", "deny" or "reassign", in the order in which they were added via
    073     * {@link #addSuccessor(Outcome, Step)}. Concrete implementations should always return a defensive copy of the outcomes, not the
    074     * original backing collection.
    075     *
    076     * @return the set of outcomes
    077     */
    078    Collection< Outcome > getAvailableOutcomes();
    079
    080    /**
    081     * Returns a List of error strings generated by this Step. If this Step generated no errors, this method returns a zero-length array.
    082     *
    083     * @return the errors
    084     */
    085    List< String > getErrors();
    086
    087    /**
    088     * <p>
    089     * Executes the processing for this Step and returns an Outcome indicating if it succeeded ({@link Outcome#STEP_COMPLETE} or
    090     * {@link Outcome#STEP_ABORT}). Processing instructions can do just about anything, such as executing custom business logic or
    091     * changing the Step's final outcome via {@link #setOutcome(Outcome)}. A return value of <code>STEP_COMPLETE</code> indicates
    092     * that the instructions executed completely, without errors; <code>STEP_ABORT</code> indicates that the Step and its parent
    093     * Workflow should be aborted (that is, fail silently without error). If the execution step encounters any errors, it should throw a
    094     * WikiException or a subclass.
    095     * </p>
    096     * <p>
    097     * Note that successful execution of this methods does not necessarily mean that the Step is considered "complete"; rather, it just
    098     * means that it has executed. Therefore, it is possible that <code>execute</code> could run multiple times.
    099     * </p>
    100     *
    101     * @param ctx executing wiki context.
    102     * @return the result of the Step, expressed as an Outcome
    103     * @throws WikiException if the step encounters errors while executing
    104     */
    105    Outcome execute( Context ctx ) throws WikiException;
    106
    107    /**
    108     * The Principal responsible for completing this Step, such as a system user or actor assigned to a Decision.
    109     *
    110     * @return the responsible Principal
    111     */
    112    Principal getActor();
    113
    114    /**
    115     * The end time for this Step. This value should be set when the step completes. Returns {@link #TIME_NOT_SET} if not completed
    116     * yet.
    117     *
    118     * @return the end time
    119     */
    120    Date getEndTime();
    121
    122    /**
    123     * Message key for human-friendly name of this Step, including any parameter substitutions. By convention, the message prefix should be
    124     * a lower-case version of the Step's type, plus a period (<em>e.g.</em>, <code>task.</code> and <code>decision.</code>).
    125     *
    126     * @return the message key for this Step.
    127     */
    128    String getMessageKey();
    129
    130    /**
    131     * Returns the Outcome of this Step's processing; by default, {@link Outcome#STEP_CONTINUE}.
    132     *
    133     * @return the outcome
    134     */
    135    Outcome getOutcome();
    136
    137    /**
    138     * The start time for this Step. Returns {@link #TIME_NOT_SET} if not started yet.
    139     *
    140     * @return the start time
    141     */
    142    Date getStartTime();
    143
    144    /**
    145     * Determines whether the Step is completed; if not, it is by definition awaiting action by the owner or in process. If a Step has
    146     * completed, it <em>must also</em> return a non-<code>null</code> result for {@link #getOutcome()}.
    147     *
    148     * @return <code>true</code> if the Step has completed; <code>false</code> if not.
    149     */
    150    boolean isCompleted();
    151
    152    /**
    153     * Determines whether the Step has started.
    154     *
    155     * @return <code>true</code> if the Step has started; <code>false</code> if not.
    156     */
    157    boolean isStarted();
    158
    159    /**
    160     * Starts the Step, and sets the start time to the moment when this method is first invoked. If this Step has already been started,
    161     * this method throws an {@linkplain IllegalStateException}. If the Step cannot be started because the underlying implementation
    162     * encounters an error, it the implementation should throw a WikiException.
    163     *
    164     * @throws WikiException if the step encounters errors while starting
    165     */
    166    void start() throws WikiException;
    167
    168    /**
    169     * Sets the current Outcome for the step. If the Outcome is a "completion" Outcome, it should also sets the completion time and mark the
    170     * Step as complete. Once a Step has been marked complete, this method cannot be called again. If the supplied Outcome is not in the
    171     * set returned by {@link #getAvailableOutcomes()}, or is not  {@link Outcome#STEP_CONTINUE} or {@link Outcome#STEP_ABORT}, this method
    172     * returns an IllegalArgumentException. If the caller attempts to set an Outcome and the Step has already completed, this method throws
    173     * an IllegalStateException.
    174     *
    175     * @param outcome whether the step should be considered completed
    176     */
    177    void setOutcome( Outcome outcome );
    178
    179    /**
    180     * Identifies the next Step for a particular Outcome; if there is no next Step for this Outcome, this method returns <code>null</code>.
    181     *
    182     * @param outcome the outcome
    183     * @return the next step
    184     */
    185    Step getSuccessor( Outcome outcome );
    186
    187    /**
    188     * Sets the parent Workflow post-construction. Should be called after building a {@link Step}.
    189     *
    190     * @param workflowId the parent workflow id to set
    191     * @param workflowContext the parent workflow context to set
    192     */
    193    void setWorkflow( final int workflowId, final Map< String, Serializable > workflowContext );
    194
    195}