KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opensymphony > workflow > spi > hibernate > HibernateWorkflowStore


1 /*
2  * Copyright (c) 2002-2003 by OpenSymphony
3  * All rights reserved.
4  */

5 package com.opensymphony.workflow.spi.hibernate;
6
7 import com.opensymphony.module.propertyset.PropertySet;
8 import com.opensymphony.module.propertyset.PropertySetManager;
9 import com.opensymphony.module.propertyset.hibernate.DefaultHibernateConfigurationProvider;
10
11 import com.opensymphony.util.TextUtils;
12
13 import com.opensymphony.workflow.StoreException;
14 import com.opensymphony.workflow.query.*;
15 import com.opensymphony.workflow.spi.Step;
16 import com.opensymphony.workflow.spi.WorkflowEntry;
17 import com.opensymphony.workflow.spi.WorkflowStore;
18
19 import net.sf.hibernate.Criteria;
20 import net.sf.hibernate.Hibernate;
21 import net.sf.hibernate.HibernateException;
22 import net.sf.hibernate.Session;
23 import net.sf.hibernate.SessionFactory;
24 import net.sf.hibernate.Transaction;
25 import net.sf.hibernate.expression.Criterion;
26 import net.sf.hibernate.expression.Expression;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import java.util.*;
32
33
34 /**
35  * A workflow store backed by Hibernate for persistence. To use this with the standard
36  * persistence factory, pass to the DefaultConfiguration.persistenceArgs the SessionFactory to
37  * use:
38  * <code>DefaultConfiguration.persistenceArgs.put("sessionFactory", DatabaseHelper.getSessionFactory());</code>
39  * See the HibernateFunctionalWorkflowTestCase for more help.
40  *
41  * @author $Author: hani $
42  * @version $Revision: 1.18 $
43  */

44 public class HibernateWorkflowStore implements WorkflowStore {
45     //~ Static fields/initializers /////////////////////////////////////////////
46

47     private static final Log log = LogFactory.getLog(HibernateWorkflowStore.class);
48
49     //~ Instance fields ////////////////////////////////////////////////////////
50

51     Session session;
52     SessionFactory sessionFactory;
53
54     //~ Constructors ///////////////////////////////////////////////////////////
55

56     public HibernateWorkflowStore() {
57     }
58
59     public HibernateWorkflowStore(SessionFactory sessionFactory) throws StoreException {
60         this.sessionFactory = sessionFactory;
61
62         try {
63             this.session = sessionFactory.openSession();
64         } catch (HibernateException he) {
65             log.error("constructor", he);
66             throw new StoreException("constructor", he);
67         }
68     }
69
70     //~ Methods ////////////////////////////////////////////////////////////////
71

72     public void setEntryState(long entryId, int state) throws StoreException {
73         try {
74             HibernateWorkflowEntry entry = (HibernateWorkflowEntry) session.find("FROM entry IN CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(entryId), Hibernate.LONG).get(0);
75             entry.setState(state);
76             session.save(entry);
77         } catch (HibernateException e) {
78             log.error("An exception occured", e);
79
80             return;
81         }
82     }
83
84     public PropertySet getPropertySet(long entryId) {
85         HashMap args = new HashMap();
86         args.put("entityName", "OSWorkflowEntry");
87         args.put("entityId", new Long JavaDoc(entryId));
88
89         DefaultHibernateConfigurationProvider configurationProvider = new DefaultHibernateConfigurationProvider();
90         configurationProvider.setSessionFactory(sessionFactory);
91
92         args.put("configurationProvider", configurationProvider);
93
94         return PropertySetManager.getInstance("hibernate", args);
95     }
96
97     public Step createCurrentStep(long entryId, int stepId, String JavaDoc owner, Date startDate, Date dueDate, String JavaDoc status, long[] previousIds) throws StoreException {
98         HibernateCurrentStep step = new HibernateCurrentStep();
99         HibernateWorkflowEntry entry;
100
101         Transaction tx;
102
103         try {
104             tx = session.beginTransaction();
105             entry = (HibernateWorkflowEntry) session.find("FROM entry in CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(entryId), Hibernate.LONG).get(0);
106         } catch (HibernateException he) {
107             log.error("Looking for workflow entry " + entryId, he);
108             throw new StoreException("Looking for workflow entry " + entryId, he);
109         }
110
111         step.setEntry(entry);
112         step.setStepId(stepId);
113         step.setOwner(owner);
114         step.setStartDate(startDate);
115         step.setDueDate(dueDate);
116         step.setStatus(status);
117
118         List stepIdList = new ArrayList(previousIds.length);
119
120         for (int i = 0; i < previousIds.length; i++) {
121             long previousId = previousIds[i];
122             stepIdList.add(new Long JavaDoc(previousId));
123         }
124
125         if (!stepIdList.isEmpty()) {
126             String JavaDoc stepIds = TextUtils.join(", ", stepIdList);
127
128             try {
129                 step.setPreviousSteps(session.find("FROM step in CLASS " + HibernateCurrentStep.class.getName() + " WHERE step.id IN (" + stepIds + ")"));
130             } catch (HibernateException he) {
131                 log.error("Looking for step in " + stepIds, he);
132                 throw new StoreException("Looking for step in " + stepIds, he);
133             }
134         } else {
135             step.setPreviousSteps(Collections.EMPTY_LIST);
136         }
137
138         if (entry.getCurrentSteps() == null) {
139             ArrayList cSteps = new ArrayList(1);
140             cSteps.add(step);
141             entry.setCurrentSteps(cSteps);
142         } else {
143             entry.getCurrentSteps().add(step);
144         }
145
146         try {
147             session.save(entry);
148             tx.commit();
149
150             //session.save(step);
151
return step;
152         } catch (HibernateException he) {
153             log.error("Saving new workflow entry", he);
154             throw new StoreException("Saving new workflow entry", he);
155         }
156     }
157
158     public WorkflowEntry createEntry(String JavaDoc workflowName) throws StoreException {
159         HibernateWorkflowEntry entry = new HibernateWorkflowEntry();
160         entry.setState(WorkflowEntry.CREATED);
161         entry.setWorkflowName(workflowName);
162
163         Transaction tx;
164
165         try {
166             tx = session.beginTransaction();
167             session.save(entry);
168             tx.commit();
169         } catch (HibernateException he) {
170             log.error("Saving new workflow entry", he);
171             throw new StoreException("Saving new workflow entry", he);
172         }
173
174         return entry;
175     }
176
177     public List findCurrentSteps(long entryId) throws StoreException {
178         HibernateWorkflowEntry entry;
179
180         try {
181             entry = (HibernateWorkflowEntry) session.find("FROM entry in CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(entryId), Hibernate.LONG).get(0);
182         } catch (HibernateException he) {
183             log.error("Looking for entryId " + entryId, he);
184             throw new StoreException("Looking for entryId " + entryId, he);
185         }
186
187         try {
188             return session.find("FROM step IN CLASS " + HibernateCurrentStep.class.getName() + " WHERE step.entry = ?", entry, Hibernate.entity(entry.getClass()));
189         } catch (HibernateException he) {
190             log.error("Looking for step id" + entry, he);
191             throw new StoreException("Looking for step id" + entry, he);
192         }
193     }
194
195     public WorkflowEntry findEntry(long entryId) throws StoreException {
196         try {
197             List result = session.find("FROM entry IN CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(entryId), Hibernate.LONG);
198
199             return (WorkflowEntry) result.get(0);
200         } catch (HibernateException he) {
201             log.error("Looking for entry " + entryId, he);
202             throw new StoreException("Loooking for entry " + entryId, he);
203         }
204     }
205
206     public List findHistorySteps(long entryId) throws StoreException {
207         HibernateWorkflowEntry entry;
208
209         try {
210             entry = (HibernateWorkflowEntry) session.find("FROM entry in CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(entryId), Hibernate.LONG).get(0);
211         } catch (HibernateException he) {
212             log.error("Finding entry " + entryId, he);
213             throw new StoreException("Finding entry " + entryId, he);
214         }
215
216         try {
217             return session.find("FROM step IN CLASS " + HibernateHistoryStep.class.getName() + " WHERE step.entry = ?", entry, Hibernate.entity(entry.getClass()));
218         } catch (HibernateException he) {
219             log.error("Looking for step with entry " + entry, he);
220             throw new StoreException("Looking for step with entry " + entry, he);
221         }
222     }
223
224     public void init(Map props) throws StoreException {
225         try {
226             //if(1==2){
227
sessionFactory = (SessionFactory) props.get("sessionFactory");
228             session = sessionFactory.openSession();
229
230             //}
231
} catch (HibernateException he) {
232             log.error("Setting sessionFactory", he);
233             throw new StoreException("Setting sessionFactory", he);
234         }
235     }
236
237     public Step markFinished(Step step, int actionId, Date finishDate, String JavaDoc status, String JavaDoc caller) throws StoreException {
238         HibernateCurrentStep currentStep = (HibernateCurrentStep) step;
239
240         currentStep.setActionId(actionId);
241         currentStep.setFinishDate(finishDate);
242         currentStep.setStatus(status);
243         currentStep.setCaller(caller);
244
245         try {
246             Transaction tx = session.beginTransaction();
247             session.save(currentStep);
248             tx.commit();
249
250             return currentStep;
251         } catch (HibernateException he) {
252             log.error("Saving current step with action " + actionId, he);
253             throw new StoreException("Saving current step with action " + actionId, he);
254         }
255     }
256
257     public void moveToHistory(Step step) throws StoreException {
258         HibernateWorkflowEntry entry;
259
260         Transaction tx;
261
262         try {
263             tx = session.beginTransaction();
264             entry = (HibernateWorkflowEntry) session.find("FROM entry IN CLASS " + HibernateWorkflowEntry.class.getName() + " WHERE entry.id = ?", new Long JavaDoc(step.getEntryId()), Hibernate.LONG).get(0);
265         } catch (HibernateException he) {
266             log.error("Looking for workflow entry " + step.getEntryId(), he);
267             throw new StoreException("Looking for workflow entry " + step.getEntryId(), he);
268         }
269
270         HibernateHistoryStep hStep = new HibernateHistoryStep((HibernateStep) step);
271
272         entry.getCurrentSteps().remove(step);
273
274         if (entry.getHistorySteps() == null) {
275             ArrayList hSteps = new ArrayList(1);
276             hSteps.add(hStep);
277             entry.setHistorySteps(hSteps);
278         } else {
279             entry.getHistorySteps().add(hStep);
280         }
281
282         try {
283             session.save(hStep);
284             session.save(entry);
285             tx.commit();
286
287             //session.delete(step);
288
//session.save(hStep, new Long(hStep.getId()));
289
} catch (HibernateException he) {
290             log.error("Saving workflow entry " + entry.getId(), he);
291             throw new StoreException("Saving workflow entry " + entry.getId(), he);
292         }
293     }
294
295     public List query(WorkflowExpressionQuery query) throws StoreException {
296         com.opensymphony.workflow.query.Expression expression = query.getExpression();
297
298         Criterion expr;
299
300         Class JavaDoc entityClass = getQueryClass(expression, null);
301
302         if (expression.isNested()) {
303             expr = buildNested((NestedExpression) expression);
304         } else {
305             expr = queryComparison((FieldExpression) expression);
306         }
307
308         //get results and send them back
309
Criteria criteria = session.createCriteria(entityClass);
310         criteria.add(expr);
311
312         try {
313             Set results = new HashSet();
314
315             Iterator iter = criteria.list().iterator();
316
317             while (iter.hasNext()) {
318                 Object JavaDoc next = iter.next();
319                 Object JavaDoc item;
320
321                 if (next instanceof HibernateStep) {
322                     HibernateStep step = (HibernateStep) next;
323                     item = new Long JavaDoc(step.getEntryId());
324                 } else {
325                     WorkflowEntry entry = (WorkflowEntry) next;
326                     item = new Long JavaDoc(entry.getId());
327                 }
328
329                 results.add(item);
330             }
331
332             return new ArrayList(results);
333         } catch (HibernateException e) {
334             throw new StoreException("Error executing query " + expression, e);
335         }
336     }
337
338     public List query(WorkflowQuery query) throws StoreException {
339         Class JavaDoc entityClass;
340
341         int qtype = query.getType();
342
343         if (qtype == 0) { // then not set, so look in sub queries
344

345             if (query.getLeft() != null) {
346                 qtype = query.getLeft().getType();
347             }
348         }
349
350         if (qtype == WorkflowQuery.CURRENT) {
351             entityClass = HibernateCurrentStep.class;
352         } else {
353             entityClass = HibernateHistoryStep.class;
354         }
355
356         Criteria criteria = session.createCriteria(entityClass);
357         Criterion expression = buildExpression(query);
358         criteria.add(expression);
359
360         //get results and send them back
361
try {
362             Set results = new HashSet();
363             Iterator iter = criteria.list().iterator();
364
365             while (iter.hasNext()) {
366                 HibernateStep step = (HibernateStep) iter.next();
367                 results.add(new Long JavaDoc(step.getEntryId()));
368             }
369
370             return new ArrayList(results);
371         } catch (HibernateException e) {
372             throw new StoreException("Error executing query " + expression, e);
373         }
374     }
375
376     /**
377      * Returns an expression generated from this query
378      */

379     private Criterion getExpression(WorkflowQuery query) {
380         int operator = query.getOperator();
381
382         switch (operator) {
383         case WorkflowQuery.EQUALS:
384             return Expression.eq(getFieldName(query.getField()), query.getValue());
385
386         case WorkflowQuery.NOT_EQUALS:
387             return Expression.not(Expression.like(getFieldName(query.getField()), query.getValue()));
388
389         case WorkflowQuery.GT:
390             return Expression.gt(getFieldName(query.getField()), query.getValue());
391
392         case WorkflowQuery.LT:
393             return Expression.lt(getFieldName(query.getField()), query.getValue());
394
395         default:
396             return Expression.eq(getFieldName(query.getField()), query.getValue());
397         }
398     }
399
400     /**
401      * returns the correct name of the field given or "1" if none is found
402      * which matches the input.
403      * @param field
404      * @return
405      */

406     private String JavaDoc getFieldName(int field) {
407         switch (field) {
408         case FieldExpression.ACTION: // actionId
409
return "actionId";
410
411         case FieldExpression.CALLER:
412             return "caller";
413
414         case FieldExpression.FINISH_DATE:
415             return "finishDate";
416
417         case FieldExpression.OWNER:
418             return "owner";
419
420         case FieldExpression.START_DATE:
421             return "startDate";
422
423         case FieldExpression.STEP: // stepId
424
return "stepId";
425
426         case FieldExpression.STATUS:
427             return "status";
428
429         case FieldExpression.STATE:
430             return "state";
431
432         case FieldExpression.NAME:
433             return "workflowName";
434
435         default:
436             return "1";
437         }
438     }
439
440     private Class JavaDoc getQueryClass(com.opensymphony.workflow.query.Expression expr, Collection classesCache) throws StoreException {
441         if (classesCache == null) {
442             classesCache = new HashSet();
443         }
444
445         if (expr instanceof FieldExpression) {
446             FieldExpression fieldExpression = (FieldExpression) expr;
447
448             switch (fieldExpression.getContext()) {
449             case FieldExpression.CURRENT_STEPS:
450                 classesCache.add(HibernateCurrentStep.class);
451
452                 break;
453
454             case FieldExpression.HISTORY_STEPS:
455                 classesCache.add(HibernateHistoryStep.class);
456
457                 break;
458
459             case FieldExpression.ENTRY:
460                 classesCache.add(HibernateWorkflowEntry.class);
461
462                 break;
463
464             default:
465                 throw new StoreException("Query for unsupported context " + fieldExpression.getContext());
466             }
467         } else {
468             NestedExpression nestedExpression = (NestedExpression) expr;
469
470             for (int i = 0; i < nestedExpression.getExpressionCount(); i++) {
471                 com.opensymphony.workflow.query.Expression expression = nestedExpression.getExpression(i);
472
473                 if (expression.isNested()) {
474                     classesCache.add(getQueryClass(nestedExpression.getExpression(i), classesCache));
475                 } else {
476                     classesCache.add(getQueryClass(expression, classesCache));
477                 }
478             }
479         }
480
481         if (classesCache.size() > 1) {
482             throw new StoreException("Store does not support nested queries of different types (types found:" + classesCache + ")");
483         }
484
485         return (Class JavaDoc) classesCache.iterator().next();
486     }
487
488     /**
489      * Recursive method for building Expressions using Query objects.
490      */

491     private Criterion buildExpression(WorkflowQuery query) throws StoreException {
492         if (query.getLeft() == null) {
493             if (query.getRight() == null) {
494                 return getExpression(query); //leaf node
495
} else {
496                 throw new StoreException("Invalid WorkflowQuery object. QueryLeft is null but QueryRight is not.");
497             }
498         } else {
499             if (query.getRight() == null) {
500                 throw new StoreException("Invalid WorkflowQuery object. QueryLeft is not null but QueryRight is.");
501             }
502
503             int operator = query.getOperator();
504             WorkflowQuery left = query.getLeft();
505             WorkflowQuery right = query.getRight();
506
507             switch (operator) {
508             case WorkflowQuery.AND:
509                 return Expression.and(buildExpression(left), buildExpression(right));
510
511             case WorkflowQuery.OR:
512                 return Expression.or(buildExpression(left), buildExpression(right));
513
514             case WorkflowQuery.XOR:
515                 throw new StoreException("XOR Operator in Queries not supported by " + this.getClass().getName());
516
517             default:
518                 throw new StoreException("Operator '" + operator + "' is not supported by " + this.getClass().getName());
519             }
520         }
521     }
522
523     private Criterion buildNested(NestedExpression nestedExpression) throws StoreException {
524         Criterion full = null;
525
526         for (int i = 0; i < nestedExpression.getExpressionCount(); i++) {
527             Criterion expr;
528             com.opensymphony.workflow.query.Expression expression = nestedExpression.getExpression(i);
529
530             if (expression.isNested()) {
531                 expr = buildNested((NestedExpression) nestedExpression.getExpression(i));
532             } else {
533                 FieldExpression sub = (FieldExpression) nestedExpression.getExpression(i);
534                 expr = queryComparison(sub);
535
536                 if (sub.isNegate()) {
537                     expr = Expression.not(expr);
538                 }
539             }
540
541             if (full == null) {
542                 full = expr;
543             } else {
544                 switch (nestedExpression.getExpressionOperator()) {
545                 case NestedExpression.AND:
546                     full = Expression.and(full, expr);
547
548                     break;
549
550                 case NestedExpression.OR:
551                     full = Expression.or(full, expr);
552                 }
553             }
554         }
555
556         return full;
557     }
558
559     private Criterion queryComparison(FieldExpression expression) {
560         int operator = expression.getOperator();
561
562         switch (operator) {
563         case FieldExpression.EQUALS:
564             return Expression.eq(getFieldName(expression.getField()), expression.getValue());
565
566         case FieldExpression.NOT_EQUALS:
567             return Expression.not(Expression.like(getFieldName(expression.getField()), expression.getValue()));
568
569         case FieldExpression.GT:
570             return Expression.gt(getFieldName(expression.getField()), expression.getValue());
571
572         case FieldExpression.LT:
573             return Expression.lt(getFieldName(expression.getField()), expression.getValue());
574
575         default:
576             return Expression.eq(getFieldName(expression.getField()), expression.getValue());
577         }
578     }
579 }
580
Popular Tags