001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.workflow;
021:
022: import java.security.Principal;
023: import java.util.Collection;
024: import java.util.Date;
025: import java.util.List;
026:
027: import com.ecyrd.jspwiki.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 com.ecyrd.jspwiki.i18n.InternationalizationManager}.
056: * See also {@link Workflow#getMessageArguments()}, which is a convenience
057: * method that returns message arguments.
058: * </p>
059: *
060: * @author Andrew Jaquith
061: * @since 2.5
062: */
063: public interface Step {
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: public 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: public Collection 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: public List 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, where <code>true</code> means success,
119: * and <code>false</code> means abort
120: * @throws WikiException
121: * if the step encounters errors while executing
122: */
123: public Outcome execute() throws WikiException;
124:
125: /**
126: * The Principal responsible for completing this Step, such as a system user
127: * or actor assigned to a Decision.
128: *
129: * @return the responsible Principal
130: */
131: public Principal getActor();
132:
133: /**
134: * The end time for this Step. This value should be set when the step
135: * completes. Returns {@link Workflow#TIME_NOT_SET} if not completed yet.
136: *
137: * @return the end time
138: */
139: public Date getEndTime();
140:
141: /**
142: * Message key for human-friendly name of this Step, including any parameter
143: * substitutions. By convention, the message prefix should be a lower-case
144: * version of the Step's type, plus a period (<em>e.g.</em>,
145: * <code>task.</code> and <code>decision.</code>).
146: *
147: * @return the message key for this Step.
148: */
149: public String getMessageKey();
150:
151: /**
152: * Returns the message arguments for this Step, typically by delegating to the
153: * parent Workflow's {@link Workflow#getMessageArguments()} method.
154: *
155: * @return the message arguments.
156: */
157: public Object[] getMessageArguments();
158:
159: /**
160: * Returns the Outcome of this Step's processing; by default,
161: * {@link Outcome#STEP_CONTINUE}.
162: *
163: * @return the outcome
164: */
165: public Outcome getOutcome();
166:
167: /**
168: * The start time for this Step. Returns {@link Workflow#TIME_NOT_SET} if
169: * not started yet.
170: *
171: * @return the start time
172: */
173: public Date getStartTime();
174:
175: /**
176: * Gets the Workflow that is the parent of this Step.
177: *
178: * @return the workflow
179: */
180: public Workflow getWorkflow();
181:
182: /**
183: * Determines whether the Step is completed; if not, it is by definition
184: * awaiting action by the owner or in process. If a Step has completed, it
185: * <em>must also</em> return a non-<code>null</code> result for
186: * {@link #getOutcome()}.
187: *
188: * @return <code>true</code> if the Step has completed; <code>false</code>
189: * if not.
190: */
191: public boolean isCompleted();
192:
193: /**
194: * Determines whether the Step has started.
195: *
196: * @return <code>true</code> if the Step has started; <code>false</code>
197: * if not.
198: */
199: public boolean isStarted();
200:
201: /**
202: * Starts the Step, and sets the start time to the moment when this method
203: * is first invoked. If this Step has already been started, this method
204: * throws an {@linkplain IllegalStateException}. If the Step cannot
205: * be started because the underlying implementation encounters an error,
206: * it the implementation should throw a WikiException.
207: *
208: * @throws WikiException if the step encounters errors while starting
209: */
210: public void start() throws WikiException;
211:
212: /**
213: * Sets the current Outcome for the step. If the Outcome is a "completion"
214: * Outcome, it should also sets the completon time and mark the Step as
215: * complete. Once a Step has been marked complete, this method cannot be
216: * called again. If the supplied Outcome is not in the set returned by
217: * {@link #getAvailableOutcomes()}, or is not {@link Outcome#STEP_CONTINUE}
218: * or {@link Outcome#STEP_ABORT}, this method returns an
219: * IllegalArgumentException. If the caller attempts to set an Outcome
220: * and the Step has already completed, this method throws an
221: * IllegalStateException.
222: *
223: * @param outcome whether the step should be considered completed
224: */
225: public void setOutcome(Outcome outcome);
226:
227: /**
228: * Convenience method that returns the owner of the Workflow by delegating
229: * to {@link Workflow#getOwner()}.
230: *
231: * @return the owner of the Workflow
232: */
233: public Principal getOwner();
234:
235: /**
236: * Identifies the next Step for a particular Outcome; if there is no next
237: * Step for this Outcome, this method returns <code>null</code>.
238: *
239: * @param outcome
240: * the outcome
241: * @return the next step
242: */
243: public Step getSuccessor(Outcome outcome);
244:
245: }
|