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