1 23 24 package org.infoglue.cms.util.workflow; 25 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.Set ; 34 35 import net.sf.hibernate.HibernateException; 36 import net.sf.hibernate.SessionFactory; 37 import net.sf.hibernate.cfg.Configuration; 38 39 import org.apache.log4j.Logger; 40 import org.infoglue.cms.entities.mydesktop.WorkflowActionVO; 41 import org.infoglue.cms.entities.mydesktop.WorkflowStepVO; 42 import org.infoglue.cms.entities.mydesktop.WorkflowVO; 43 import org.infoglue.cms.exception.SystemException; 44 import org.infoglue.cms.security.InfoGluePrincipal; 45 import org.infoglue.deliver.util.CacheController; 46 47 import com.opensymphony.module.propertyset.PropertySet; 48 import com.opensymphony.workflow.AbstractWorkflow; 49 import com.opensymphony.workflow.InvalidActionException; 50 import com.opensymphony.workflow.WorkflowException; 51 import com.opensymphony.workflow.basic.BasicWorkflow; 52 import com.opensymphony.workflow.loader.ActionDescriptor; 53 import com.opensymphony.workflow.loader.StepDescriptor; 54 import com.opensymphony.workflow.loader.WorkflowDescriptor; 55 import com.opensymphony.workflow.query.Expression; 56 import com.opensymphony.workflow.query.FieldExpression; 57 import com.opensymphony.workflow.query.NestedExpression; 58 import com.opensymphony.workflow.query.WorkflowExpressionQuery; 59 import com.opensymphony.workflow.spi.Step; 60 import com.opensymphony.workflow.spi.WorkflowEntry; 61 62 70 public class WorkflowFacade 71 { 72 76 private static final String WORKFLOW_TITLE_EXTENSION_META_ATTRIBUTE = "org.infoglue.title"; 77 78 82 private static final String WORKFLOW_DATABASE_EXTENSION_META_ATTRIBUTE = "org.infoglue.database"; 83 84 85 private final static Logger logger = Logger.getLogger(WorkflowFacade.class.getName()); 86 87 private static SessionFactory hibernateSessionFactory; 88 89 static 90 { 91 try 92 { 93 hibernateSessionFactory = new Configuration().configure().buildSessionFactory(); 94 } 95 catch (HibernateException e) 96 { 97 e.printStackTrace(); 98 throw new ExceptionInInitializerError (e); 99 } 100 } 101 102 105 private static final Collection currentWorkflows = new ArrayList (); 106 107 private final AbstractWorkflow workflow; 108 private long workflowId; 109 110 private WorkflowDescriptor workflowDescriptor; 111 112 117 public WorkflowFacade(final Owner owner) 118 { 119 workflow = new InfoGlueBasicWorkflow(owner.getIdentifier()); 120 workflow.getConfiguration().getPersistenceArgs().put("sessionFactory", hibernateSessionFactory); 122 } 123 124 128 public WorkflowFacade(InfoGluePrincipal userPrincipal) 129 { 130 this(OwnerFactory.create(userPrincipal)); 131 } 132 133 141 public WorkflowFacade(InfoGluePrincipal userPrincipal, String name, int initialAction) throws SystemException 142 { 143 this(userPrincipal, name, initialAction, new HashMap ()); 144 } 145 146 155 public WorkflowFacade(InfoGluePrincipal userPrincipal, String name, int initialAction, Map inputs) throws SystemException 156 { 157 this(userPrincipal); 158 initialize(name, initialAction, inputs); 159 } 160 161 166 public WorkflowFacade(InfoGluePrincipal userPrincipal, long workflowId) 167 { 168 this(userPrincipal); 169 setWorkflowIdAndDescriptor(workflowId); 170 } 171 172 176 private void setWorkflowIdAndDescriptor(long workflowId) 177 { 178 this.workflowId = workflowId; 179 String key = "workflowName_" + workflowId; 180 String workflowName = (String )CacheController.getCachedObject("workflowNameCache", key); 181 if(workflowName == null) 182 { 183 workflowName = workflow.getWorkflowName(workflowId); 184 CacheController.cacheObject("workflowNameCache", key, workflowName); 185 } 186 187 workflowDescriptor = workflow.getWorkflowDescriptor(workflowName); 188 } 189 190 194 public long getWorkflowId() 195 { 196 return workflowId; 197 } 198 199 206 private void initialize(String name, int initialAction, Map inputs) throws SystemException 207 { 208 try 209 { 210 if(useDatabaseExtension(workflow.getWorkflowDescriptor(name))) 211 { 212 setWorkflowIdAndDescriptor(doExtendedInitialize(name, initialAction, inputs)); 213 } 214 else 215 { 216 setWorkflowIdAndDescriptor(workflow.initialize(name, initialAction, inputs)); 217 } 218 } 219 catch (Exception e) 220 { 221 throw new SystemException(e); 222 } 223 } 224 225 234 private long doExtendedInitialize(final String name, final int initialAction, final Map inputs) throws WorkflowException 235 { 236 long result = 0; 237 final DatabaseSession db = new DatabaseSession(); 238 try 239 { 240 final Map copy = new HashMap (); 241 copy.putAll(inputs); 242 copy.put(workflow.getWorkflowDescriptor(name).getMetaAttributes().get(WORKFLOW_DATABASE_EXTENSION_META_ATTRIBUTE), db); 243 result = workflow.initialize(name, initialAction, copy); 244 } 245 catch(Exception e) 246 { 247 e.printStackTrace(); 248 if(db != null) 249 { 250 db.setRollbackOnly(); 251 } 252 throw (e instanceof WorkflowException) ? (WorkflowException) e : new WorkflowException(e); 253 } 254 finally 255 { 256 db.releaseDB(); 257 } 258 return result; 259 } 260 261 267 public void doAction(int actionId, Map inputs) throws WorkflowException 268 { 269 final Long id = new Long (workflowId); 270 synchronized(currentWorkflows) 271 { 272 if(!isActive()) 273 { 274 throw new InvalidActionException("Workflow " + workflowId + " is no longer active"); 275 } 276 if(currentWorkflows.contains(id)) 277 { 278 throw new WorkflowException("The selected workflow is executing..."); 279 } 280 currentWorkflows.add(id); 281 } 282 283 try 284 { 285 if(useDatabaseExtension(workflowDescriptor)) 286 { 287 doExtendedAction(actionId, inputs); 288 } 289 else 290 { 291 workflow.doAction(workflowId, actionId, inputs); 292 } 293 } 294 finally 295 { 296 synchronized(currentWorkflows) 297 { 298 currentWorkflows.remove(id); 299 } 300 } 301 } 302 303 311 private void doExtendedAction(final int actionId, final Map inputs) throws WorkflowException 312 { 313 final DatabaseSession db = new DatabaseSession(); 314 try 315 { 316 final Map copy = new HashMap (); 317 copy.putAll(inputs); 318 copy.put(workflowDescriptor.getMetaAttributes().get(WORKFLOW_DATABASE_EXTENSION_META_ATTRIBUTE), db); 319 workflow.doAction(workflowId, actionId, copy); 320 } 321 catch(Exception e) 322 { 323 e.printStackTrace(); 324 if(db != null) 325 { 326 db.setRollbackOnly(); 327 } 328 throw (e instanceof WorkflowException) ? (WorkflowException) e : new WorkflowException(e); 329 } 330 finally 331 { 332 db.releaseDB(); 333 } 334 } 335 336 340 public PropertySet getPropertySet() 341 { 342 return workflow.getPropertySet(workflowId); 343 } 344 345 349 private int getEntryState() 350 { 351 return workflow.getEntryState(workflowId); 352 } 353 354 359 public boolean isActive() 360 { 361 return getEntryState() == WorkflowEntry.ACTIVATED; 362 } 363 364 369 public boolean isFinished() 370 { 371 int state = getEntryState(); 372 return state == WorkflowEntry.KILLED || state == WorkflowEntry.COMPLETED; 373 } 374 375 379 public List getDeclaredWorkflows() 380 { 381 String [] workflowNames = workflow.getWorkflowNames(); 382 List availableWorkflows = new ArrayList (); 383 384 for (int i = 0; i < workflowNames.length; i++) 385 { 386 try 387 { 388 availableWorkflows.add(createWorkflowVO(workflowNames[i])); 389 } 390 catch(Exception e) 391 { 392 logger.error("The workflow " + workflowNames[i] + " could not be instantiated:" + e.getMessage(), e); 393 } 394 } 395 396 return availableWorkflows; 397 } 398 399 405 public List getActiveWorkflows() throws SystemException 406 { 407 List workflowVOs = new ArrayList (); 408 409 for (Iterator workflows = findActiveWorkflows().iterator(); workflows.hasNext();) 410 { 411 setWorkflowIdAndDescriptor(((Long )workflows.next()).longValue()); 412 logger.info("workflowId:" + workflowId); 413 workflowVOs.add(createWorkflowVO()); 414 } 415 416 return workflowVOs; 417 } 418 419 426 427 public List getMyActiveWorkflows(final InfoGluePrincipal principal) throws SystemException 428 { 429 String key = "myWorkflows_" + principal.getName(); 430 List workflows = (List )CacheController.getCachedObject("myActiveWorkflows", key); 431 if(workflows == null) 432 { 433 if(principal.getIsAdministrator()) 434 { 435 workflows = getActiveWorkflows(); 436 } 437 438 Collection owners = OwnerFactory.createAll(principal); 439 Expression[] expressions = new Expression[owners.size()]; 440 441 Iterator ownersIterator = owners.iterator(); 442 int i = 0; 443 while(ownersIterator.hasNext()) 444 { 445 Owner owner = (Owner)ownersIterator.next(); 446 Expression expression = new FieldExpression(FieldExpression.OWNER, FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, owner.getIdentifier()); 447 expressions[i] = expression; 448 i++; 449 } 450 451 final Set workflowVOs = new HashSet (); 452 workflowVOs.addAll(createWorkflowsForOwner(expressions)); 453 454 462 463 workflows = new ArrayList (workflowVOs); 464 CacheController.cacheObject("myActiveWorkflows", key, workflows); 465 } 466 467 return workflows; 468 } 469 470 477 private final Set createWorkflowsForOwner(final Owner owner) throws SystemException 478 { 479 final Set workflowVOs = new HashSet (); 480 List workflows = findWorkflows(owner); 481 Iterator workflowsIterator = workflows.iterator(); 482 while (workflowsIterator.hasNext()) 483 { 484 setWorkflowIdAndDescriptor(((Long )workflowsIterator.next()).longValue()); 485 workflowVOs.add(createWorkflowVO()); 486 } 487 return workflowVOs; 488 } 489 490 497 private final Set createWorkflowsForOwner(final Expression[] expressions) throws SystemException 498 { 499 final Set workflowVOs = new HashSet (); 500 List workflows = findWorkflows(expressions); 501 Iterator workflowsIterator = workflows.iterator(); 502 while (workflowsIterator.hasNext()) 503 { 504 setWorkflowIdAndDescriptor(((Long )workflowsIterator.next()).longValue()); 505 workflowVOs.add(createWorkflowVO()); 506 } 507 return workflowVOs; 508 } 509 510 515 private List findActiveWorkflows() throws SystemException 516 { 517 try 518 { 519 return workflow.query(new WorkflowExpressionQuery(new FieldExpression(FieldExpression.STATE, 520 FieldExpression.ENTRY, FieldExpression.EQUALS, new Integer (WorkflowEntry.ACTIVATED)))); 521 } 522 catch (WorkflowException e) 523 { 524 throw new SystemException(e); 525 } 526 } 527 528 535 private List findWorkflows(final Owner owner) throws SystemException 536 { 537 try 538 { 539 List workflows = workflow.query(new WorkflowExpressionQuery(new FieldExpression(FieldExpression.OWNER, 540 FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, owner.getIdentifier()))); 541 542 return workflows; 543 } 544 catch (WorkflowException e) 545 { 546 throw new SystemException(e); 547 } 548 } 549 550 557 private List findWorkflows(final Expression[] expressions) throws SystemException 558 { 559 try 560 { 561 List workflows = workflow.query(new WorkflowExpressionQuery(new NestedExpression(expressions, NestedExpression.OR))); 562 563 return workflows; 565 } 566 catch (WorkflowException e) 567 { 568 throw new SystemException(e); 569 } 570 } 571 572 578 public List getCurrentSteps() 579 { 580 return getCurrentSteps(null); 581 } 582 583 public List getCurrentSteps(final WorkflowVO workflowVO) 584 { 585 return createStepVOs(workflowVO, workflow.getCurrentSteps(workflowId)); 586 } 587 588 592 public List getHistorySteps() 593 { 594 return getHistorySteps(null); 595 } 596 597 public List getHistorySteps(final WorkflowVO workflowVO) 598 { 599 return createStepVOs(workflowVO, workflow.getHistorySteps(workflowId)); 600 } 601 602 607 public List getDeclaredSteps() 608 { 609 return getDeclaredSteps(workflowDescriptor); 610 } 611 612 617 private List createStepVOs(final WorkflowVO workflowVO, final List steps) 618 { 619 List stepVOs = new ArrayList (); 620 for (Iterator i = steps.iterator(); i.hasNext();) 621 { 622 Step step = null; 623 try 624 { 625 step = (Step)i.next(); 626 stepVOs.add(createStepVO(workflowVO, step)); 627 } 628 catch(Exception e) 629 { 630 logger.warn("There was an invalid step:" + workflowVO, e); 631 } 632 } 633 634 return stepVOs; 635 } 636 637 643 private List getDeclaredSteps(WorkflowDescriptor descriptor) 644 { 645 List steps = new ArrayList (); 646 for (Iterator i = descriptor.getSteps().iterator(); i.hasNext();) 647 steps.add(createStepVO((StepDescriptor)i.next())); 648 649 return steps; 650 } 651 652 656 private List getInitialActions() 657 { 658 return createActionVOs(workflowDescriptor.getInitialActions()); 659 } 660 661 665 private List getGlobalActions() 666 { 667 return createActionVOs(workflowDescriptor.getGlobalActions()); 668 } 669 670 675 private List createActionVOs(List actionDescriptors) 676 { 677 List actions = new ArrayList (); 678 for (Iterator i = actionDescriptors.iterator(); i.hasNext();) 679 actions.add(createActionVO((ActionDescriptor)i.next())); 680 681 return actions; 682 683 } 684 685 690 public WorkflowVO createWorkflowVO() 691 { 692 WorkflowVO workflowVO = new WorkflowVO(new Long (workflowId), workflow.getWorkflowName(workflowId)); 693 if(workflowDescriptor != null) 694 { 695 if(useTitleExtension(workflowDescriptor)) 696 workflowVO.setTitle(getWorkflowTitle()); 697 } 698 699 workflowVO.setCurrentSteps(getCurrentSteps(workflowVO)); 700 workflowVO.setHistorySteps(getHistorySteps(workflowVO)); 701 workflowVO.setInitialActions(getInitialActions()); 702 workflowVO.setGlobalActions(getGlobalActions()); 703 704 return workflowVO; 705 } 706 707 712 private String getWorkflowTitle() 713 { 714 if(!workflowDescriptor.getMetaAttributes().containsKey(WORKFLOW_TITLE_EXTENSION_META_ATTRIBUTE)) 715 { 716 return null; 717 } 718 719 final String key = (String ) workflowDescriptor.getMetaAttributes().get(WORKFLOW_TITLE_EXTENSION_META_ATTRIBUTE); 720 final PropertySet ps = getPropertySet(); 721 return ps.exists(key) ? ps.getString(key) : null; 722 } 723 724 730 private WorkflowVO createWorkflowVO(String name) 731 { 732 WorkflowVO workflowVO = new WorkflowVO(null, name); 733 try 734 { 735 workflowVO.setDeclaredSteps(getDeclaredSteps(workflow.getWorkflowDescriptor(name))); 736 } 737 catch(Exception e) 738 { 739 workflowVO.setStatus(WorkflowVO.STATUS_NOT_OK); 740 workflowVO.setStatusMessage("Error in workflow:" + e.getMessage()); 741 742 logger.error("Could not read workflow:" + e.getMessage(), e); 743 } 744 745 return workflowVO; 746 } 747 748 753 private WorkflowStepVO createStepVO(final WorkflowVO workflowVO, final Step step) throws Exception 754 { 755 logger.info("step:" + step + ':' + step.getId()); 756 logger.info("Owner:" + step.getOwner()); 757 758 WorkflowStepVO stepVO = new WorkflowStepVO(workflowVO); 759 stepVO.setId(new Integer ((int)step.getId())); stepVO.setStepId(new Integer (step.getStepId())); 761 stepVO.setWorkflowId(new Long (workflowId)); 762 stepVO.setStatus(step.getStatus()); 763 stepVO.setStartDate(step.getStartDate()); 764 stepVO.setFinishDate(step.getFinishDate()); 765 stepVO.setOwner(step.getOwner()); 766 stepVO.setCaller(step.getCaller()); 767 768 StepDescriptor stepDescriptor = workflowDescriptor.getStep(step.getStepId()); 769 if(stepDescriptor != null) 770 { 771 stepVO.setName(stepDescriptor.getName()); 772 for (Iterator i = stepDescriptor.getActions().iterator(); i.hasNext();) 773 stepVO.addAction(createActionVO((ActionDescriptor)i.next())); 774 } 775 else 776 { 777 throw new SystemException("No stepDescriptor found for " + step); 778 } 779 780 return stepVO; 781 } 782 783 789 private WorkflowStepVO createStepVO(StepDescriptor stepDescriptor) 790 { 791 WorkflowStepVO step = new WorkflowStepVO(); 792 step.setStepId(new Integer (stepDescriptor.getId())); 793 step.setName(stepDescriptor.getName()); 794 step.setStatus("Not started"); 795 796 for (Iterator i = stepDescriptor.getActions().iterator(); i.hasNext();) 797 step.addAction(createActionVO((ActionDescriptor)i.next())); 798 799 return step; 800 } 801 802 807 private WorkflowActionVO createActionVO(ActionDescriptor actionDescriptor) 808 { 809 logger.info("Action:" + actionDescriptor.getId() + ':' + actionDescriptor.getName() 810 + ':' + actionDescriptor.getParent().getClass()); 811 812 WorkflowActionVO actionVO = new WorkflowActionVO(new Integer (actionDescriptor.getId())); 813 actionVO.setWorkflowId(new Long (workflowId)); 814 actionVO.setName(actionDescriptor.getName()); 815 actionVO.setView(actionDescriptor.getView()); 816 actionVO.setAutoExecute(actionDescriptor.getAutoExecute()); 817 actionVO.setMetaAttributes(actionDescriptor.getMetaAttributes()); 818 return actionVO; 819 } 820 821 826 private boolean useTitleExtension(final WorkflowDescriptor descriptor) 827 { 828 return descriptor.getMetaAttributes().containsKey(WORKFLOW_TITLE_EXTENSION_META_ATTRIBUTE); 829 } 830 831 836 private boolean useDatabaseExtension(final WorkflowDescriptor descriptor) 837 { 838 return descriptor.getMetaAttributes().containsKey(WORKFLOW_DATABASE_EXTENSION_META_ATTRIBUTE); 839 } 840 } 841 | Popular Tags |