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