001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: /*
006: * Created on Feb 11, 2004
007: *
008: *
009: */
010: package com.opensymphony.workflow.spi.prevayler;
011:
012: import com.opensymphony.module.propertyset.PropertySet;
013:
014: import com.opensymphony.workflow.StoreException;
015: import com.opensymphony.workflow.query.WorkflowExpressionQuery;
016: import com.opensymphony.workflow.query.WorkflowQuery;
017: import com.opensymphony.workflow.spi.Step;
018: import com.opensymphony.workflow.spi.WorkflowEntry;
019: import com.opensymphony.workflow.spi.WorkflowStore;
020:
021: import org.prevayler.Prevayler;
022: import org.prevayler.PrevaylerFactory;
023: import org.prevayler.Query;
024: import org.prevayler.Transaction;
025: import org.prevayler.TransactionWithQuery;
026:
027: import java.io.IOException;
028: import java.io.Serializable;
029:
030: import java.util.Date;
031: import java.util.List;
032: import java.util.Map;
033:
034: /**
035: *
036: * This is a WorkflowStore implementation which uses Prevaylence as its datastore.
037: * See http://www.prevayler.org/wiki.jsp
038: *
039: * It creates a transient or non-transient store depending upon the properties set.
040: *
041: * @author Christopher Farnham
042: **/
043: public class PrevaylerWorkflowStore implements WorkflowStore,
044: Serializable {
045: //~ Instance fields ////////////////////////////////////////////////////////
046:
047: private transient Prevayler _prevayler = null;
048: private transient String _prevalenceBase;
049: private WorkflowStore _store = null;
050:
051: //~ Constructors ///////////////////////////////////////////////////////////
052:
053: public PrevaylerWorkflowStore() throws IOException,
054: ClassNotFoundException {
055: this ("WorkflowPrevaylenceBase");
056: }
057:
058: public PrevaylerWorkflowStore(String prevalenceBase)
059: throws IOException, ClassNotFoundException {
060: super ();
061: _prevalenceBase = prevalenceBase;
062: _store = new WorkflowSystem();
063: }
064:
065: //~ Methods ////////////////////////////////////////////////////////////////
066:
067: /* (non-Javadoc)
068: * @see com.opensymphony.workflow.spi.WorkflowStore#setEntryState(long, int)
069: */
070: public void setEntryState(long entryId, int state)
071: throws StoreException {
072: Object[] o = { new Long(entryId), new Integer(state) };
073:
074: try {
075: _prevayler.execute(new TransactionImpl(o) {
076: public void execute(WorkflowSystem store) {
077: Object[] o = (Object[]) _object;
078: long entryId = ((Long) o[0]).longValue();
079: int state = ((Integer) o[1]).intValue();
080:
081: try {
082: store.setEntryState(entryId, state);
083: } catch (StoreException e) {
084: throw new RuntimeException(e);
085: }
086: }
087: });
088: } catch (Exception e) {
089: if (e.getCause() instanceof StoreException) {
090: throw ((StoreException) e.getCause());
091: } else {
092: throw new StoreException(e);
093: }
094: }
095: }
096:
097: /* (non-Javadoc)
098: * @see com.opensymphony.workflow.spi.WorkflowStore#getPropertySet(long)
099: */
100: public PropertySet getPropertySet(long entryId)
101: throws StoreException {
102: try {
103: return (PropertySet) _prevayler
104: .execute(new TransactionWithQueryImpl(new Long(
105: entryId)) {
106: public Object execute(WorkflowSystem store)
107: throws StoreException {
108: return store
109: .getPropertySet(((Long) _object)
110: .longValue());
111: }
112: });
113: } catch (Exception e) {
114: throw new StoreException(e);
115: }
116: }
117:
118: /* (non-Javadoc)
119: * @see com.opensymphony.workflow.spi.WorkflowStore#createCurrentStep(long, int, java.lang.String, java.util.Date, java.util.Date, java.lang.String, long[])
120: */
121: public Step createCurrentStep(long entryId, int stepId,
122: String owner, Date startDate, Date dueDate, String status,
123: long[] previousIds) throws StoreException {
124: Object[] oArray = { new Long(entryId), new Integer(stepId),
125: owner, startDate, dueDate, status, previousIds };
126:
127: try {
128: return (Step) _prevayler
129: .execute(new TransactionWithQueryImpl(oArray) {
130: public Object execute(WorkflowSystem store)
131: throws StoreException {
132: Object[] o = (Object[]) _object;
133: long entryId = ((Long) o[0]).longValue();
134: int stepId = ((Integer) o[1]).intValue();
135: String owner = (String) o[2];
136: Date startDate = (Date) o[3];
137: Date dueDate = (Date) o[4];
138: String status = (String) o[5];
139: long[] previousIds = (long[]) o[6];
140:
141: return store.createCurrentStep(entryId,
142: stepId, owner, startDate, dueDate,
143: status, previousIds);
144: }
145: });
146: } catch (Exception e) {
147: throw new StoreException(e);
148: }
149: }
150:
151: /* (non-Javadoc)
152: * @see com.opensymphony.workflow.spi.WorkflowStore#createEntry(java.lang.String)
153: */
154: public WorkflowEntry createEntry(String workflowName)
155: throws StoreException {
156: try {
157: return (WorkflowEntry) _prevayler
158: .execute(new TransactionWithQueryImpl(workflowName) {
159: public Object execute(WorkflowSystem store)
160: throws StoreException {
161: return store
162: .createEntry(((String) _object));
163: }
164: });
165: } catch (Exception e) {
166: throw new StoreException(e);
167: }
168: }
169:
170: /* (non-Javadoc)
171: * @see com.opensymphony.workflow.spi.WorkflowStore#findCurrentSteps(long)
172: */
173: public List findCurrentSteps(long entryId) throws StoreException {
174: try {
175: return (List) _prevayler
176: .execute(new TransactionWithQueryImpl(new Long(
177: entryId)) {
178: public Object execute(WorkflowSystem store)
179: throws StoreException {
180: return store
181: .findCurrentSteps(((Long) _object)
182: .longValue());
183: }
184: });
185: } catch (Exception e) {
186: throw new StoreException(e);
187: }
188: }
189:
190: /* (non-Javadoc)
191: * @see com.opensymphony.workflow.spi.WorkflowStore#findEntry(long)
192: */
193: public WorkflowEntry findEntry(long entryId) throws StoreException {
194: try {
195: return (WorkflowEntry) _prevayler
196: .execute(new TransactionWithQueryImpl(new Long(
197: entryId)) {
198: public Object execute(WorkflowSystem store)
199: throws StoreException {
200: return store.findEntry(((Long) _object)
201: .longValue());
202: }
203: });
204: } catch (Exception e) {
205: throw new StoreException(e);
206: }
207: }
208:
209: /* (non-Javadoc)
210: * @see com.opensymphony.workflow.spi.WorkflowStore#findHistorySteps(long)
211: */
212: public List findHistorySteps(long entryId) throws StoreException {
213: try {
214: return (List) _prevayler
215: .execute(new TransactionWithQueryImpl(new Long(
216: entryId)) {
217: public Object execute(WorkflowSystem store)
218: throws StoreException {
219: return store
220: .findHistorySteps(((Long) _object)
221: .longValue());
222: }
223: });
224: } catch (Exception e) {
225: throw new StoreException(e);
226: }
227: }
228:
229: /* (non-Javadoc)
230: * @see com.opensymphony.workflow.spi.WorkflowStore#init(java.util.Map)
231: */
232: public void init(Map props) throws StoreException {
233: _store.init(props);
234:
235: boolean isTransient = false;
236: String pBaseKey = "base";
237:
238: if (props.containsKey(pBaseKey)) {
239: _prevalenceBase = (String) props.get(pBaseKey);
240: }
241:
242: String transientKey = "transient";
243:
244: if (props.containsKey(transientKey)) {
245: String value = (String) props.get(transientKey);
246:
247: if (value.equalsIgnoreCase("true")) {
248: isTransient = true;
249: }
250: }
251:
252: try {
253: initializePrevaylenceSystem(_prevalenceBase, isTransient);
254: } catch (Exception e) {
255: throw new StoreException(e);
256: }
257: }
258:
259: /* (non-Javadoc)
260: * @see com.opensymphony.workflow.spi.WorkflowStore#markFinished(com.opensymphony.workflow.spi.Step, int, java.util.Date, java.lang.String, java.lang.String)
261: */
262: public Step markFinished(Step step, int actionId, Date finishDate,
263: String status, String caller) throws StoreException {
264: Object[] oArray = { step, new Integer(actionId), finishDate,
265: status, caller };
266:
267: try {
268: return (Step) _prevayler
269: .execute(new TransactionWithQueryImpl(oArray) {
270: public Object execute(WorkflowSystem store)
271: throws StoreException {
272: Object[] o = (Object[]) _object;
273: Step step = (Step) o[0];
274: int actionId = ((Integer) o[1]).intValue();
275: Date finishDate = (Date) o[2];
276: String status = (String) o[3];
277: String caller = (String) o[4];
278:
279: return store.markFinished(step, actionId,
280: finishDate, status, caller);
281: }
282: });
283: } catch (Exception e) {
284: throw new StoreException(e);
285: }
286: }
287:
288: /* (non-Javadoc)
289: * @see com.opensymphony.workflow.spi.WorkflowStore#moveToHistory(com.opensymphony.workflow.spi.Step)
290: */
291: public void moveToHistory(Step step) throws StoreException {
292: try {
293: _prevayler.execute(new TransactionImpl(step) {
294: public void execute(WorkflowSystem store)
295: throws StoreException {
296: store.moveToHistory(((Step) _object));
297: }
298: });
299: } catch (Exception e) {
300: throw new StoreException(e);
301: }
302: }
303:
304: /* (non-Javadoc)
305: * @see com.opensymphony.workflow.spi.WorkflowStore#query(com.opensymphony.workflow.query.WorkflowQuery)
306: */
307: public List query(WorkflowQuery query) throws StoreException {
308: try {
309: return (List) _prevayler.execute(new QueryImpl(query) {
310: public Object execute(WorkflowSystem store)
311: throws StoreException {
312: return store.query(((WorkflowQuery) _object));
313: }
314: });
315: } catch (Exception e) {
316: throw new StoreException(e);
317: }
318: }
319:
320: /* (non-Javadoc)
321: * @see com.opensymphony.workflow.spi.WorkflowStore#query(com.opensymphony.workflow.query.WorkflowExpressionQuery)
322: */
323: public List query(WorkflowExpressionQuery query)
324: throws StoreException {
325: try {
326: return (List) _prevayler.execute(new QueryImpl(query) {
327: public Object execute(WorkflowSystem store)
328: throws StoreException {
329: return store
330: .query(((WorkflowExpressionQuery) _object));
331: }
332: });
333: } catch (Exception e) {
334: throw new StoreException(e);
335: }
336: }
337:
338: /**
339: * @param prevalenceBase
340: */
341: private void initializePrevaylenceSystem(String prevalenceBase,
342: boolean isTransient) throws IOException,
343: ClassNotFoundException {
344: if (isTransient) {
345: _prevayler = PrevaylerFactory
346: .createTransientPrevayler(((Serializable) _store));
347: } else {
348: _prevayler = PrevaylerFactory.createPrevayler(
349: ((Serializable) _store), prevalenceBase);
350: }
351: }
352:
353: //~ Inner Classes //////////////////////////////////////////////////////////
354:
355: private class ObjectActioner implements Serializable {
356: protected Object _object = null;
357:
358: public ObjectActioner() {
359: }
360:
361: public ObjectActioner(Object object) {
362: _object = object;
363: }
364: }
365:
366: private abstract class QueryImpl extends ObjectActioner implements
367: Query {
368: public QueryImpl(Object object) {
369: super (object);
370: }
371:
372: public abstract Object execute(WorkflowSystem store)
373: throws StoreException;
374:
375: public Object query(Object prevSystem, Date ignored)
376: throws Exception {
377: return execute(((WorkflowSystem) prevSystem));
378: }
379: }
380:
381: private abstract class TransactionImpl extends ObjectActioner
382: implements Transaction {
383: public TransactionImpl(Object object) {
384: super (object);
385: }
386:
387: public abstract void execute(WorkflowSystem store)
388: throws StoreException;
389:
390: public void executeOn(Object prevSystem, Date ignored) {
391: try {
392: execute(((WorkflowSystem) prevSystem));
393: } catch (StoreException e) {
394: throw new RuntimeException(e);
395: }
396: }
397: }
398:
399: private abstract class TransactionWithQueryImpl extends
400: ObjectActioner implements TransactionWithQuery {
401: public TransactionWithQueryImpl(Object object) {
402: super (object);
403: }
404:
405: public abstract Object execute(WorkflowSystem store)
406: throws StoreException;
407:
408: public Object executeAndQuery(Object prevSystem, Date ignored)
409: throws Exception {
410: return execute(((WorkflowSystem) prevSystem));
411: }
412: }
413: }
|