001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.engine;
046:
047: import org.obe.spi.WorkflowContext;
048: import org.obe.spi.event.ApplicationEvent;
049: import org.obe.spi.model.ActivityInstance;
050: import org.obe.spi.model.ProcessInstance;
051: import org.obe.spi.model.WorkItem;
052: import org.obe.spi.service.ServiceManager;
053: import org.obe.xpdl.model.activity.Activity;
054: import org.obe.xpdl.model.activity.Tool;
055: import org.obe.xpdl.model.workflow.WorkflowProcess;
056:
057: import java.util.Stack;
058:
059: /**
060: * The EngineContext exposes runtime data for a workflow instance. When a
061: * new EngineContext is created, it associates itself with the current thread,
062: * and can be retrieved from any stack frame on the same thread by calling the
063: * static {@link #peekContext} method.
064: *
065: * @author Adrian Price
066: */
067: public class EngineContext implements WorkflowContext {
068: private static ThreadLocal _contexts = new ThreadLocal();
069: private final WorkflowEngine _engine;
070: private final WorkflowProcess _workflow;
071: private final ProcessInstance _processInstance;
072: private Activity _activity;
073: private Tool _tool;
074: private ActivityInstance _activityInstance;
075: private WorkItem _workItem;
076: private ApplicationEvent _event;
077:
078: private static Stack getContextStack() {
079: Stack stack = (Stack) _contexts.get();
080: if (stack == null) {
081: stack = new Stack();
082: _contexts.set(stack);
083: }
084: return stack;
085: }
086:
087: /**
088: * Returns the workflow context associated with the current thread.
089: *
090: * @return The workflow context.
091: */
092: public static EngineContext peekContext() {
093: Stack contextStack = getContextStack();
094: return contextStack.isEmpty() ? null
095: : (EngineContext) contextStack.peek();
096: }
097:
098: /**
099: * Returns the workflow context for a particular process instance on the
100: * current thread. The method examines the call stack to determine whether
101: * the specified process instance is being processed on the current thread.
102: * If it is, the method returns the corresponding workflow context.
103: *
104: * @return The workflow context, or <code>null</code> if the process
105: * instance is not on the call stack.
106: */
107: public static EngineContext peekContext(String processInstanceId) {
108: EngineContext ctx = null;
109: Stack stack = getContextStack();
110: for (int i = stack.size() - 1; i >= 0; i--) {
111: EngineContext ec = (EngineContext) stack.get(i);
112: if (ec._processInstance.getProcessInstanceId().equals(
113: processInstanceId)) {
114:
115: ctx = ec;
116: break;
117: }
118: }
119: return ctx;
120: }
121:
122: /**
123: * Pops the workflow context associated with the current thread.
124: *
125: * @return The workflow context.
126: */
127: public static EngineContext popContext() {
128: Stack contextStack = getContextStack();
129: return contextStack.isEmpty() ? null
130: : (EngineContext) contextStack.pop();
131: }
132:
133: /**
134: * Pushes a new workflow context onto the current thread.
135: */
136: public static EngineContext pushContext(WorkflowEngine engine,
137: WorkflowProcess workflow, ProcessInstance processInstance) {
138:
139: return pushContext(engine, workflow, processInstance, null,
140: null, null, null);
141: }
142:
143: /**
144: * Pushes a new workflow context onto the current thread.
145: */
146: public static EngineContext pushContext(WorkflowEngine engine,
147: ApplicationEvent event) {
148:
149: return pushContext(engine, null, null, null, null, null, event);
150: }
151:
152: /**
153: * Pushes a new workflow context onto the current thread.
154: */
155: public static EngineContext pushContext(WorkflowEngine engine,
156: WorkflowProcess workflow, ProcessInstance processInstance,
157: Activity activity, ActivityInstance activityInstance,
158: WorkItem workItem, ApplicationEvent event) {
159:
160: EngineContext ctx = new EngineContext(engine, workflow,
161: processInstance, event);
162: ctx.setActivityContext(activity, activityInstance);
163: ctx.setWorkItem(workItem);
164: getContextStack().push(ctx);
165: return ctx;
166: }
167:
168: /**
169: * Construct a new EngineContext.
170: *
171: * @param engine The WorkflowEngine.
172: */
173: private EngineContext(WorkflowEngine engine,
174: WorkflowProcess workflow, ProcessInstance processInstance,
175: ApplicationEvent event) {
176:
177: _engine = engine;
178: _workflow = workflow;
179: _processInstance = processInstance;
180: _event = event;
181: }
182:
183: public boolean equals(Object obj) {
184: return this == obj
185: || obj instanceof EngineContext
186: && _processInstance
187: .equals(((EngineContext) obj)._processInstance);
188: }
189:
190: /**
191: * Returns the activity definition that is currently being enacted.
192: *
193: * @return The activity definition.
194: */
195: public Activity getActivity() {
196: return _activity;
197: }
198:
199: /**
200: * Returns the activity instance that is currently being enacted.
201: *
202: * @return The activity instance.
203: */
204: public ActivityInstance getActivityInstance() {
205: return _activityInstance;
206: }
207:
208: /**
209: * Returns the work item that is currently being enacted.
210: *
211: * @return The work item.
212: */
213: public WorkItem getWorkItem() {
214: return _workItem;
215: }
216:
217: /**
218: * Sets the work item that is currently being enacted.
219: *
220: * @param workItem The work item.
221: */
222: public void setWorkItem(WorkItem workItem) {
223: _workItem = workItem;
224: }
225:
226: /**
227: * Returns the tool invocation that is currently being enacted.
228: *
229: * @return The tool invocation.
230: */
231: public Tool getTool() {
232: return _tool;
233: }
234:
235: /**
236: * Sets the tool invocation that is currently being enacted.
237: *
238: * @param tool The tool invocation.
239: */
240: public void setTool(Tool tool) {
241: _tool = tool;
242: }
243:
244: /**
245: * Returns the workflow engine in which the workflow is currently being
246: * executed.
247: *
248: * @return The workflow engine.
249: */
250: public WorkflowEngine getEngine() {
251: return _engine;
252: }
253:
254: public ServiceManager getServiceManager() {
255: return _engine.getServiceManager();
256: }
257:
258: /**
259: * Returns the application context for the event currently being processed.
260: *
261: * @return The application context.
262: */
263: public Object getApplication() {
264: return _event == null ? null : _event.getApplication();
265: }
266:
267: /**
268: * Returns the application event that is being processed.
269: *
270: * @return The application event.
271: */
272: public ApplicationEvent getEvent() {
273: return _event;
274: }
275:
276: /**
277: * Sets the application event that is being processed.
278: *
279: * @param event The application event.
280: */
281: public void setEvent(ApplicationEvent event) {
282: _event = event;
283: }
284:
285: /**
286: * Returns the process instance being enacted in this context.
287: *
288: * @return The process instance.
289: */
290: public ProcessInstance getProcessInstance() {
291: return _processInstance;
292: }
293:
294: /**
295: * Returns the workflow definition that is currently being enacted.
296: *
297: * @return The workflow process definition.
298: */
299: public WorkflowProcess getWorkflow() {
300: return _workflow;
301: }
302:
303: public int hashCode() {
304: return Integer
305: .parseInt(_processInstance.getProcessInstanceId());
306: }
307:
308: /**
309: * Sets the activity context that is currently being enacted.
310: *
311: * @param activity The activity definition.
312: * @param instance The activity instance.
313: */
314: public void setActivityContext(Activity activity,
315: ActivityInstance instance) {
316:
317: _activity = activity;
318: _activityInstance = instance;
319: _workItem = null;
320: _tool = null;
321: }
322:
323: public String toString() {
324: return "EngineContext[workflow=" + _workflow + ", activity="
325: + _activity + ", tool=" + _tool + ", processInstance="
326: + _processInstance + ", activityInstance="
327: + _activityInstance + ", workItem=" + _workItem
328: + ", event=" + _event + ']';
329: }
330: }
|