1 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.FieldExpression; 15 import com.opensymphony.workflow.query.NestedExpression; 16 import com.opensymphony.workflow.query.WorkflowExpressionQuery; 17 import com.opensymphony.workflow.query.WorkflowQuery; 18 import com.opensymphony.workflow.spi.Step; 19 import com.opensymphony.workflow.spi.WorkflowEntry; 20 import com.opensymphony.workflow.spi.WorkflowStore; 21 22 import net.sf.hibernate.Criteria; 23 import net.sf.hibernate.HibernateException; 24 import net.sf.hibernate.expression.Criterion; 25 import net.sf.hibernate.expression.Expression; 26 27 import org.apache.commons.logging.Log; 28 import org.apache.commons.logging.LogFactory; 29 30 import org.springframework.orm.hibernate.support.HibernateDaoSupport; 31 32 import java.util.ArrayList ; 33 import java.util.Collection ; 34 import java.util.Collections ; 35 import java.util.Date ; 36 import java.util.HashMap ; 37 import java.util.HashSet ; 38 import java.util.Iterator ; 39 import java.util.List ; 40 import java.util.Map ; 41 import java.util.Set ; 42 43 44 50 public class SpringHibernateWorkflowStore extends HibernateDaoSupport implements WorkflowStore { 51 53 private static final Log log = LogFactory.getLog(SpringHibernateWorkflowStore.class); 54 55 57 public void setEntryState(long entryId, int state) throws StoreException { 58 HibernateWorkflowEntry entry = loadEntry(entryId); 59 entry.setState(state); 60 getHibernateTemplate().update(entry); 61 } 62 63 public PropertySet getPropertySet(long entryId) throws StoreException { 64 HashMap args = new HashMap (); 65 args.put("entityName", "OSWorkflowEntry"); 66 args.put("entityId", new Long (entryId)); 67 68 DefaultHibernateConfigurationProvider configurationProvider = new DefaultHibernateConfigurationProvider(); 69 configurationProvider.setSessionFactory(getSessionFactory()); 70 71 args.put("configurationProvider", configurationProvider); 72 73 return PropertySetManager.getInstance("hibernate", args); 74 } 75 76 public Step createCurrentStep(long entryId, int stepId, String owner, Date startDate, Date dueDate, String status, long[] previousIds) throws StoreException { 77 HibernateCurrentStep step = new HibernateCurrentStep(); 78 HibernateWorkflowEntry entry = loadEntry(entryId); 79 80 step.setEntry(entry); 81 step.setStepId(stepId); 82 step.setOwner(owner); 83 step.setStartDate(startDate); 84 step.setDueDate(dueDate); 85 step.setStatus(status); 86 87 List stepIdList = new ArrayList (previousIds.length); 88 89 for (int i = 0; i < previousIds.length; i++) { 90 long previousId = previousIds[i]; 91 stepIdList.add(new Long (previousId)); 92 } 93 94 if (!stepIdList.isEmpty()) { 95 String stepIds = TextUtils.join(", ", stepIdList); 96 step.setPreviousSteps(getHibernateTemplate().find("FROM " + HibernateCurrentStep.class.getName() + " step WHERE step.id IN (" + stepIds + ")")); 97 } else { 98 step.setPreviousSteps(Collections.EMPTY_LIST); 99 } 100 101 getHibernateTemplate().save(step); 102 103 return step; 104 } 105 106 public WorkflowEntry createEntry(String workflowName) throws StoreException { 107 HibernateWorkflowEntry entry = new HibernateWorkflowEntry(); 108 entry.setState(WorkflowEntry.CREATED); 109 entry.setWorkflowName(workflowName); 110 getHibernateTemplate().save(entry); 111 112 return entry; 113 } 114 115 public List findCurrentSteps(long entryId) throws StoreException { 116 return getHibernateTemplate().find("FROM " + HibernateCurrentStep.class.getName() + " step WHERE step.entry.id = ?", new Long (entryId)); 117 } 118 119 public WorkflowEntry findEntry(long entryId) throws StoreException { 120 return loadEntry(entryId); 121 } 122 123 public List findHistorySteps(long entryId) throws StoreException { 124 return getHibernateTemplate().find("FROM " + HibernateHistoryStep.class.getName() + " step WHERE step.entry.id = ?", new Long (entryId)); 125 } 126 127 public void init(Map props) throws StoreException { 128 } 130 131 public Step markFinished(Step step, int actionId, Date finishDate, String status, String caller) throws StoreException { 132 HibernateCurrentStep currentStep = (HibernateCurrentStep) step; 133 134 currentStep.setActionId(actionId); 135 currentStep.setFinishDate(finishDate); 136 currentStep.setStatus(status); 137 currentStep.setCaller(caller); 138 getHibernateTemplate().update(currentStep); 139 140 return currentStep; 141 } 142 143 public void moveToHistory(Step step) throws StoreException { 144 HibernateHistoryStep hStep = new HibernateHistoryStep((HibernateStep) step); 145 getHibernateTemplate().delete(step); 146 getHibernateTemplate().save(hStep); 147 } 148 149 public List query(WorkflowQuery query) throws StoreException { 150 Class entityClass; 151 152 int qtype = query.getType(); 153 154 if (qtype == 0) { 156 if (query.getLeft() != null) { 157 qtype = query.getLeft().getType(); 158 } 159 } 160 161 if (qtype == WorkflowQuery.CURRENT) { 162 entityClass = HibernateCurrentStep.class; 163 } else { 164 entityClass = HibernateHistoryStep.class; 165 } 166 167 Criteria criteria = getSession().createCriteria(entityClass); 168 Criterion expression = buildExpression(query); 169 criteria.add(expression); 170 171 try { 173 Set results = new HashSet (); 174 Iterator iter = criteria.list().iterator(); 175 176 while (iter.hasNext()) { 177 HibernateStep step = (HibernateStep) iter.next(); 178 results.add(new Long (step.getEntryId())); 179 } 180 181 return new ArrayList (results); 182 } catch (HibernateException e) { 183 throw new StoreException("Error executing query " + expression, e); 184 } 185 } 186 187 190 public List query(WorkflowExpressionQuery query) throws StoreException { 191 com.opensymphony.workflow.query.Expression expression = query.getExpression(); 192 193 Criterion expr; 194 195 Class entityClass = getQueryClass(expression, null); 196 197 if (expression.isNested()) { 198 expr = buildNested((NestedExpression) expression); 199 } else { 200 expr = queryComparison((FieldExpression) expression); 201 } 202 203 Criteria criteria = getSession().createCriteria(entityClass); 204 criteria.add(expr); 205 206 try { 207 Set results = new HashSet (); 208 209 Iterator iter = criteria.list().iterator(); 210 211 while (iter.hasNext()) { 212 Object next = iter.next(); 213 Object item; 214 215 if (next instanceof HibernateStep) { 216 HibernateStep step = (HibernateStep) next; 217 item = new Long (step.getEntryId()); 218 } else { 219 WorkflowEntry entry = (WorkflowEntry) next; 220 item = new Long (entry.getId()); 221 } 222 223 results.add(item); 224 } 225 226 return new ArrayList (results); 227 } catch (HibernateException e) { 228 throw new StoreException("Error executing query " + expression, e); 229 } 230 } 231 232 private Criterion getExpression(WorkflowQuery query) { 233 int operator = query.getOperator(); 234 235 switch (operator) { 236 case WorkflowQuery.EQUALS: 237 return Expression.eq(getFieldName(query.getField()), query.getValue()); 238 239 case WorkflowQuery.NOT_EQUALS: 240 return Expression.not(Expression.like(getFieldName(query.getField()), query.getValue())); 241 242 case WorkflowQuery.GT: 243 return Expression.gt(getFieldName(query.getField()), query.getValue()); 244 245 case WorkflowQuery.LT: 246 return Expression.lt(getFieldName(query.getField()), query.getValue()); 247 248 default: 249 return Expression.eq(getFieldName(query.getField()), query.getValue()); 250 } 251 } 252 253 private String getFieldName(int field) { 254 switch (field) { 255 case FieldExpression.ACTION: return "actionId"; 257 258 case FieldExpression.CALLER: 259 return "caller"; 260 261 case FieldExpression.FINISH_DATE: 262 return "finishDate"; 263 264 case FieldExpression.OWNER: 265 return "owner"; 266 267 case FieldExpression.START_DATE: 268 return "startDate"; 269 270 case FieldExpression.STEP: return "stepId"; 272 273 case FieldExpression.STATUS: 274 return "status"; 275 276 case FieldExpression.STATE: 277 return "state"; 278 279 case FieldExpression.NAME: 280 return "workflowName"; 281 282 default: 283 return "1"; 284 } 285 } 286 287 private Class getQueryClass(com.opensymphony.workflow.query.Expression expr, Collection classesCache) throws StoreException { 288 if (classesCache == null) { 289 classesCache = new HashSet (); 290 } 291 292 if (expr instanceof FieldExpression) { 293 FieldExpression fieldExpression = (FieldExpression) expr; 294 295 switch (fieldExpression.getContext()) { 296 case FieldExpression.CURRENT_STEPS: 297 classesCache.add(HibernateCurrentStep.class); 298 299 break; 300 301 case FieldExpression.HISTORY_STEPS: 302 classesCache.add(HibernateHistoryStep.class); 303 304 break; 305 306 case FieldExpression.ENTRY: 307 classesCache.add(HibernateWorkflowEntry.class); 308 309 break; 310 311 default: 312 throw new StoreException("Query for unsupported context " + fieldExpression.getContext()); 313 } 314 } else { 315 NestedExpression nestedExpression = (NestedExpression) expr; 316 317 for (int i = 0; i < nestedExpression.getExpressionCount(); i++) { 318 com.opensymphony.workflow.query.Expression expression = nestedExpression.getExpression(i); 319 320 if (expression.isNested()) { 321 classesCache.add(getQueryClass(nestedExpression.getExpression(i), classesCache)); 322 } else { 323 classesCache.add(getQueryClass(expression, classesCache)); 324 } 325 } 326 } 327 328 if (classesCache.size() > 1) { 329 throw new StoreException("Store does not support nested queries of different types (types found:" + classesCache + ")"); 330 } 331 332 return (Class ) classesCache.iterator().next(); 333 } 334 335 private Criterion buildExpression(WorkflowQuery query) throws StoreException { 336 if (query.getLeft() == null) { 337 if (query.getRight() == null) { 338 return getExpression(query); } else { 340 throw new StoreException("Invalid WorkflowQuery object. QueryLeft is null but QueryRight is not."); 341 } 342 } else { 343 if (query.getRight() == null) { 344 throw new StoreException("Invalid WorkflowQuery object. QueryLeft is not null but QueryRight is."); 345 } 346 347 int operator = query.getOperator(); 348 WorkflowQuery left = query.getLeft(); 349 WorkflowQuery right = query.getRight(); 350 351 switch (operator) { 352 case WorkflowQuery.AND: 353 return Expression.and(buildExpression(left), buildExpression(right)); 354 355 case WorkflowQuery.OR: 356 return Expression.or(buildExpression(left), buildExpression(right)); 357 358 case WorkflowQuery.XOR: 359 throw new StoreException("XOR Operator in Queries not supported by " + this.getClass().getName()); 360 361 default: 362 throw new StoreException("Operator '" + operator + "' is not supported by " + this.getClass().getName()); 363 } 364 } 365 } 366 367 private Criterion buildNested(NestedExpression nestedExpression) throws StoreException { 368 Criterion full = null; 369 370 for (int i = 0; i < nestedExpression.getExpressionCount(); i++) { 371 Criterion expr; 372 com.opensymphony.workflow.query.Expression expression = nestedExpression.getExpression(i); 373 374 if (expression.isNested()) { 375 expr = buildNested((NestedExpression) nestedExpression.getExpression(i)); 376 } else { 377 FieldExpression sub = (FieldExpression) nestedExpression.getExpression(i); 378 expr = queryComparison(sub); 379 380 if (sub.isNegate()) { 381 expr = Expression.not(expr); 382 } 383 } 384 385 if (full == null) { 386 full = expr; 387 } else { 388 switch (nestedExpression.getExpressionOperator()) { 389 case NestedExpression.AND: 390 full = Expression.and(full, expr); 391 392 break; 393 394 case NestedExpression.OR: 395 full = Expression.or(full, expr); 396 } 397 } 398 } 399 400 return full; 401 } 402 403 private HibernateWorkflowEntry loadEntry(long entryId) { 404 return (HibernateWorkflowEntry) getHibernateTemplate().load(HibernateWorkflowEntry.class, new Long (entryId)); 405 } 406 407 private Criterion queryComparison(FieldExpression expression) { 408 int operator = expression.getOperator(); 409 410 switch (operator) { 411 case FieldExpression.EQUALS: 412 return Expression.eq(getFieldName(expression.getField()), expression.getValue()); 413 414 case FieldExpression.NOT_EQUALS: 415 return Expression.not(Expression.like(getFieldName(expression.getField()), expression.getValue())); 416 417 case FieldExpression.GT: 418 return Expression.gt(getFieldName(expression.getField()), expression.getValue()); 419 420 case FieldExpression.LT: 421 return Expression.lt(getFieldName(expression.getField()), expression.getValue()); 422 423 default: 424 return Expression.eq(getFieldName(expression.getField()), expression.getValue()); 425 } 426 } 427 } 428 | Popular Tags |