Source Code Cross Referenced for AbstractWorkflow.java in  » Workflow-Engines » OSWorkflow » com » opensymphony » workflow » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » OSWorkflow » com.opensymphony.workflow 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2002-2003 by OpenSymphony
0003:         * All rights reserved.
0004:         */
0005:        package com.opensymphony.workflow;
0006:
0007:        import com.opensymphony.module.propertyset.PropertySet;
0008:        import com.opensymphony.module.propertyset.PropertySetManager;
0009:
0010:        import com.opensymphony.workflow.config.Configuration;
0011:        import com.opensymphony.workflow.config.DefaultConfiguration;
0012:        import com.opensymphony.workflow.loader.*;
0013:        import com.opensymphony.workflow.query.WorkflowExpressionQuery;
0014:        import com.opensymphony.workflow.query.WorkflowQuery;
0015:        import com.opensymphony.workflow.spi.*;
0016:        import com.opensymphony.workflow.util.VariableResolver;
0017:
0018:        import org.apache.commons.logging.Log;
0019:        import org.apache.commons.logging.LogFactory;
0020:
0021:        import java.util.*;
0022:
0023:        /**
0024:         * Abstract workflow instance that serves as the base for specific implementations, such as EJB or SOAP.
0025:         *
0026:         * @author <a href="mailto:plightbo@hotmail.com">Pat Lightbody</a>
0027:         * @author Hani Suleiman
0028:         */
0029:        public class AbstractWorkflow implements  Workflow {
0030:            //~ Static fields/initializers /////////////////////////////////////////////
0031:
0032:            private static final Log log = LogFactory
0033:                    .getLog(AbstractWorkflow.class);
0034:
0035:            //~ Instance fields ////////////////////////////////////////////////////////
0036:
0037:            protected WorkflowContext context;
0038:            private Configuration configuration;
0039:            private ThreadLocal stateCache = new ThreadLocal();
0040:            private TypeResolver typeResolver;
0041:
0042:            //~ Constructors ///////////////////////////////////////////////////////////
0043:
0044:            public AbstractWorkflow() {
0045:                stateCache.set(new HashMap());
0046:            }
0047:
0048:            //~ Methods ////////////////////////////////////////////////////////////////
0049:
0050:            /**
0051:             * @ejb.interface-method
0052:             * @deprecated use {@link #getAvailableActions(long, Map)}  with an empty Map instead.
0053:             */
0054:            public int[] getAvailableActions(long id) {
0055:                return getAvailableActions(id, new HashMap());
0056:            }
0057:
0058:            /**
0059:             * Get the available actions for the specified workflow instance.
0060:             * @ejb.interface-method
0061:             * @param id The workflow instance id.
0062:             * @param inputs The inputs map to pass on to conditions
0063:             * @return An array of action id's that can be performed on the specified entry.
0064:             * @throws IllegalArgumentException if the specified id does not exist, or if its workflow
0065:             * descriptor is no longer available or has become invalid.
0066:             */
0067:            public int[] getAvailableActions(long id, Map inputs) {
0068:                try {
0069:                    WorkflowStore store = getPersistence();
0070:                    WorkflowEntry entry = store.findEntry(id);
0071:
0072:                    if (entry == null) {
0073:                        throw new IllegalArgumentException(
0074:                                "No such workflow id " + id);
0075:                    }
0076:
0077:                    if (entry.getState() != WorkflowEntry.ACTIVATED) {
0078:                        return new int[0];
0079:                    }
0080:
0081:                    WorkflowDescriptor wf = getConfiguration().getWorkflow(
0082:                            entry.getWorkflowName());
0083:
0084:                    if (wf == null) {
0085:                        throw new IllegalArgumentException("No such workflow "
0086:                                + entry.getWorkflowName());
0087:                    }
0088:
0089:                    List l = new ArrayList();
0090:                    PropertySet ps = store.getPropertySet(id);
0091:                    Map transientVars = (inputs == null) ? new HashMap()
0092:                            : new HashMap(inputs);
0093:                    Collection currentSteps = store.findCurrentSteps(id);
0094:
0095:                    populateTransientMap(entry, transientVars, wf
0096:                            .getRegisters(), new Integer(0), currentSteps, ps);
0097:
0098:                    // get global actions
0099:                    List globalActions = wf.getGlobalActions();
0100:
0101:                    for (Iterator iterator = globalActions.iterator(); iterator
0102:                            .hasNext();) {
0103:                        ActionDescriptor action = (ActionDescriptor) iterator
0104:                                .next();
0105:                        RestrictionDescriptor restriction = action
0106:                                .getRestriction();
0107:                        ConditionsDescriptor conditions = null;
0108:
0109:                        transientVars.put("actionId", new Integer(action
0110:                                .getId()));
0111:
0112:                        if (restriction != null) {
0113:                            conditions = restriction.getConditionsDescriptor();
0114:                        }
0115:
0116:                        //todo verify that 0 is the right currentStepId
0117:                        if (passesConditions(wf.getGlobalConditions(),
0118:                                transientVars, ps, 0)
0119:                                && passesConditions(conditions, transientVars,
0120:                                        ps, 0)) {
0121:                            l.add(new Integer(action.getId()));
0122:                        }
0123:                    }
0124:
0125:                    // get normal actions
0126:                    for (Iterator iterator = currentSteps.iterator(); iterator
0127:                            .hasNext();) {
0128:                        Step step = (Step) iterator.next();
0129:                        l.addAll(getAvailableActionsForStep(wf, step,
0130:                                transientVars, ps));
0131:                    }
0132:
0133:                    int[] actions = new int[l.size()];
0134:
0135:                    for (int i = 0; i < actions.length; i++) {
0136:                        actions[i] = ((Integer) l.get(i)).intValue();
0137:                    }
0138:
0139:                    return actions;
0140:                } catch (Exception e) {
0141:                    log.error("Error checking available actions", e);
0142:
0143:                    return new int[0];
0144:                }
0145:            }
0146:
0147:            /**
0148:             * @ejb.interface-method
0149:             */
0150:            public void setConfiguration(Configuration configuration) {
0151:                this .configuration = configuration;
0152:            }
0153:
0154:            /**
0155:             * Get the configuration for this workflow.
0156:             * This method also checks if the configuration has been initialized, and if not, initializes it.
0157:             * @return The configuration that was set.
0158:             * If no configuration was set, then the default (static) configuration is returned.
0159:             *
0160:             */
0161:            public Configuration getConfiguration() {
0162:                Configuration config = (configuration != null) ? configuration
0163:                        : DefaultConfiguration.INSTANCE;
0164:
0165:                if (!config.isInitialized()) {
0166:                    try {
0167:                        config.load(null);
0168:                    } catch (FactoryException e) {
0169:                        log.fatal("Error initialising configuration", e);
0170:
0171:                        //fail fast, better to blow up with an NPE that hide the error
0172:                        return null;
0173:                    }
0174:                }
0175:
0176:                return config;
0177:            }
0178:
0179:            /**
0180:             * @ejb.interface-method
0181:             */
0182:            public List getCurrentSteps(long id) {
0183:                try {
0184:                    WorkflowStore store = getPersistence();
0185:
0186:                    return store.findCurrentSteps(id);
0187:                } catch (StoreException e) {
0188:                    log.error("Error checking current steps for instance #"
0189:                            + id, e);
0190:
0191:                    return Collections.EMPTY_LIST;
0192:                }
0193:            }
0194:
0195:            /**
0196:             * @ejb.interface-method
0197:             */
0198:            public int getEntryState(long id) {
0199:                try {
0200:                    WorkflowStore store = getPersistence();
0201:
0202:                    return store.findEntry(id).getState();
0203:                } catch (StoreException e) {
0204:                    log.error("Error checking instance state for instance #"
0205:                            + id, e);
0206:                }
0207:
0208:                return WorkflowEntry.UNKNOWN;
0209:            }
0210:
0211:            /**
0212:             * @ejb.interface-method
0213:             */
0214:            public List getHistorySteps(long id) {
0215:                try {
0216:                    WorkflowStore store = getPersistence();
0217:
0218:                    return store.findHistorySteps(id);
0219:                } catch (StoreException e) {
0220:                    log.error(
0221:                            "Error getting history steps for instance #" + id,
0222:                            e);
0223:                }
0224:
0225:                return Collections.EMPTY_LIST;
0226:            }
0227:
0228:            /**
0229:             * @ejb.interface-method
0230:             */
0231:            public Properties getPersistenceProperties() {
0232:                Properties p = new Properties();
0233:                Iterator iter = getConfiguration().getPersistenceArgs()
0234:                        .entrySet().iterator();
0235:
0236:                while (iter.hasNext()) {
0237:                    Map.Entry entry = (Map.Entry) iter.next();
0238:                    p.setProperty((String) entry.getKey(), (String) entry
0239:                            .getValue());
0240:                }
0241:
0242:                return p;
0243:            }
0244:
0245:            /**
0246:             * Get the PropertySet for the specified workflow ID
0247:             * @ejb.interface-method
0248:             * @param id The workflow ID
0249:             */
0250:            public PropertySet getPropertySet(long id) {
0251:                PropertySet ps = null;
0252:
0253:                try {
0254:                    ps = getPersistence().getPropertySet(id);
0255:                } catch (StoreException e) {
0256:                    log.error("Error getting propertyset for instance #" + id,
0257:                            e);
0258:                }
0259:
0260:                return ps;
0261:            }
0262:
0263:            public void setResolver(TypeResolver resolver) {
0264:                this .typeResolver = resolver;
0265:            }
0266:
0267:            public TypeResolver getResolver() {
0268:                if (typeResolver == null) {
0269:                    typeResolver = TypeResolver.getResolver();
0270:                }
0271:
0272:                return typeResolver;
0273:            }
0274:
0275:            /**
0276:             * @ejb.interface-method
0277:             */
0278:            public List getSecurityPermissions(long id) {
0279:                return getSecurityPermissions(id, null);
0280:            }
0281:
0282:            /**
0283:             * @ejb.interface-method
0284:             */
0285:            public List getSecurityPermissions(long id, Map inputs) {
0286:                try {
0287:                    WorkflowStore store = getPersistence();
0288:                    WorkflowEntry entry = store.findEntry(id);
0289:                    WorkflowDescriptor wf = getConfiguration().getWorkflow(
0290:                            entry.getWorkflowName());
0291:
0292:                    PropertySet ps = store.getPropertySet(id);
0293:                    Map transientVars = (inputs == null) ? new HashMap()
0294:                            : new HashMap(inputs);
0295:                    Collection currentSteps = store.findCurrentSteps(id);
0296:                    populateTransientMap(entry, transientVars, wf
0297:                            .getRegisters(), null, currentSteps, ps);
0298:
0299:                    List s = new ArrayList();
0300:
0301:                    for (Iterator interator = currentSteps.iterator(); interator
0302:                            .hasNext();) {
0303:                        Step step = (Step) interator.next();
0304:
0305:                        int stepId = step.getStepId();
0306:
0307:                        StepDescriptor xmlStep = wf.getStep(stepId);
0308:
0309:                        List securities = xmlStep.getPermissions();
0310:
0311:                        for (Iterator iterator2 = securities.iterator(); iterator2
0312:                                .hasNext();) {
0313:                            PermissionDescriptor security = (PermissionDescriptor) iterator2
0314:                                    .next();
0315:
0316:                            // to have the permission, the condition must be met or not specified
0317:                            // securities can't have restrictions based on inputs, so it's null
0318:                            if (security.getRestriction() != null) {
0319:                                if (passesConditions(security.getRestriction()
0320:                                        .getConditionsDescriptor(),
0321:                                        transientVars, ps, xmlStep.getId())) {
0322:                                    s.add(security.getName());
0323:                                }
0324:                            }
0325:                        }
0326:                    }
0327:
0328:                    return s;
0329:                } catch (Exception e) {
0330:                    log.error(
0331:                            "Error getting security permissions for instance #"
0332:                                    + id, e);
0333:                }
0334:
0335:                return Collections.EMPTY_LIST;
0336:            }
0337:
0338:            /**
0339:             * Returns a workflow definition object associated with the given name.
0340:             *
0341:             * @param workflowName the name of the workflow
0342:             * @return the object graph that represents a workflow definition
0343:             * @ejb.interface-method
0344:             */
0345:            public WorkflowDescriptor getWorkflowDescriptor(String workflowName) {
0346:                try {
0347:                    return getConfiguration().getWorkflow(workflowName);
0348:                } catch (FactoryException e) {
0349:                    log.error("Error loading workflow " + workflowName, e);
0350:                }
0351:
0352:                return null;
0353:            }
0354:
0355:            /**
0356:             * @ejb.interface-method
0357:             */
0358:            public String getWorkflowName(long id) {
0359:                try {
0360:                    WorkflowStore store = getPersistence();
0361:                    WorkflowEntry entry = store.findEntry(id);
0362:
0363:                    if (entry != null) {
0364:                        return entry.getWorkflowName();
0365:                    }
0366:                } catch (StoreException e) {
0367:                    log.error(
0368:                            "Error getting instance name for instance #" + id,
0369:                            e);
0370:                }
0371:
0372:                return null;
0373:            }
0374:
0375:            /**
0376:             * Get a list of workflow names available
0377:             * @return String[] an array of workflow names.
0378:             * @ejb.interface-method
0379:             */
0380:            public String[] getWorkflowNames() {
0381:                try {
0382:                    return getConfiguration().getWorkflowNames();
0383:                } catch (FactoryException e) {
0384:                    log.error("Error getting workflow names", e);
0385:                }
0386:
0387:                return new String[0];
0388:            }
0389:
0390:            /**
0391:             * @ejb.interface-method
0392:             */
0393:            public boolean canInitialize(String workflowName, int initialAction) {
0394:                return canInitialize(workflowName, initialAction, null);
0395:            }
0396:
0397:            /**
0398:             * @ejb.interface-method
0399:             * @param workflowName the name of the workflow to check
0400:             * @param initialAction The initial action to check
0401:             * @param inputs the inputs map
0402:             * @return true if the workflow can be initialized
0403:             */
0404:            public boolean canInitialize(String workflowName,
0405:                    int initialAction, Map inputs) {
0406:                final String mockWorkflowName = workflowName;
0407:                WorkflowEntry mockEntry = new WorkflowEntry() {
0408:                    public long getId() {
0409:                        return 0;
0410:                    }
0411:
0412:                    public String getWorkflowName() {
0413:                        return mockWorkflowName;
0414:                    }
0415:
0416:                    public boolean isInitialized() {
0417:                        return false;
0418:                    }
0419:
0420:                    public int getState() {
0421:                        return WorkflowEntry.CREATED;
0422:                    }
0423:                };
0424:
0425:                // since no state change happens here, a memory instance is just fine
0426:                PropertySet ps = PropertySetManager.getInstance("memory", null);
0427:                Map transientVars = new HashMap();
0428:
0429:                if (inputs != null) {
0430:                    transientVars.putAll(inputs);
0431:                }
0432:
0433:                try {
0434:                    populateTransientMap(mockEntry, transientVars,
0435:                            Collections.EMPTY_LIST, new Integer(initialAction),
0436:                            Collections.EMPTY_LIST, ps);
0437:
0438:                    return canInitialize(workflowName, initialAction,
0439:                            transientVars, ps);
0440:                } catch (InvalidActionException e) {
0441:                    log.error(e.getMessage());
0442:
0443:                    return false;
0444:                } catch (WorkflowException e) {
0445:                    log.error("Error checking canInitialize", e);
0446:
0447:                    return false;
0448:                }
0449:            }
0450:
0451:            /**
0452:             * @ejb.interface-method
0453:             */
0454:            public boolean canModifyEntryState(long id, int newState) {
0455:                try {
0456:                    WorkflowStore store = getPersistence();
0457:                    WorkflowEntry entry = store.findEntry(id);
0458:                    int currentState = entry.getState();
0459:                    boolean result = false;
0460:
0461:                    switch (newState) {
0462:                    case WorkflowEntry.COMPLETED:
0463:
0464:                        if (currentState == WorkflowEntry.ACTIVATED) {
0465:                            result = true;
0466:                        }
0467:
0468:                        break;
0469:
0470:                    case WorkflowEntry.CREATED:
0471:                        result = false;
0472:
0473:                    case WorkflowEntry.ACTIVATED:
0474:
0475:                        if ((currentState == WorkflowEntry.CREATED)
0476:                                || (currentState == WorkflowEntry.SUSPENDED)) {
0477:                            result = true;
0478:                        }
0479:
0480:                        break;
0481:
0482:                    case WorkflowEntry.SUSPENDED:
0483:
0484:                        if (currentState == WorkflowEntry.ACTIVATED) {
0485:                            result = true;
0486:                        }
0487:
0488:                        break;
0489:
0490:                    case WorkflowEntry.KILLED:
0491:
0492:                        if ((currentState == WorkflowEntry.CREATED)
0493:                                || (currentState == WorkflowEntry.ACTIVATED)
0494:                                || (currentState == WorkflowEntry.SUSPENDED)) {
0495:                            result = true;
0496:                        }
0497:
0498:                        break;
0499:
0500:                    default:
0501:                        result = false;
0502:
0503:                        break;
0504:                    }
0505:
0506:                    return result;
0507:                } catch (StoreException e) {
0508:                    log.error("Error checking state modifiable for instance #"
0509:                            + id, e);
0510:                }
0511:
0512:                return false;
0513:            }
0514:
0515:            public void changeEntryState(long id, int newState)
0516:                    throws WorkflowException {
0517:                WorkflowStore store = getPersistence();
0518:                WorkflowEntry entry = store.findEntry(id);
0519:
0520:                if (entry.getState() == newState) {
0521:                    return;
0522:                }
0523:
0524:                if (canModifyEntryState(id, newState)) {
0525:                    if ((newState == WorkflowEntry.KILLED)
0526:                            || (newState == WorkflowEntry.COMPLETED)) {
0527:                        Collection currentSteps = getCurrentSteps(id);
0528:
0529:                        if (currentSteps.size() > 0) {
0530:                            completeEntry(null, id, currentSteps, newState);
0531:                        }
0532:                    }
0533:
0534:                    store.setEntryState(id, newState);
0535:                } else {
0536:                    throw new InvalidEntryStateException(
0537:                            "Can't transition workflow instance #" + id
0538:                                    + ". Current state is " + entry.getState()
0539:                                    + ", requested state is " + newState);
0540:                }
0541:
0542:                if (log.isDebugEnabled()) {
0543:                    log.debug(entry.getId() + " : State is now : "
0544:                            + entry.getState());
0545:                }
0546:            }
0547:
0548:            public void doAction(long id, int actionId, Map inputs)
0549:                    throws WorkflowException {
0550:                WorkflowStore store = getPersistence();
0551:                WorkflowEntry entry = store.findEntry(id);
0552:
0553:                if (entry.getState() != WorkflowEntry.ACTIVATED) {
0554:                    return;
0555:                }
0556:
0557:                WorkflowDescriptor wf = getConfiguration().getWorkflow(
0558:                        entry.getWorkflowName());
0559:
0560:                List currentSteps = store.findCurrentSteps(id);
0561:                ActionDescriptor action = null;
0562:
0563:                PropertySet ps = store.getPropertySet(id);
0564:                Map transientVars = new HashMap();
0565:
0566:                if (inputs != null) {
0567:                    transientVars.putAll(inputs);
0568:                }
0569:
0570:                populateTransientMap(entry, transientVars, wf.getRegisters(),
0571:                        new Integer(actionId), currentSteps, ps);
0572:
0573:                boolean validAction = false;
0574:
0575:                //check global actions
0576:                for (Iterator gIter = wf.getGlobalActions().iterator(); !validAction
0577:                        && gIter.hasNext();) {
0578:                    ActionDescriptor actionDesc = (ActionDescriptor) gIter
0579:                            .next();
0580:
0581:                    if (actionDesc.getId() == actionId) {
0582:                        action = actionDesc;
0583:
0584:                        if (isActionAvailable(action, transientVars, ps, 0)) {
0585:                            validAction = true;
0586:                        }
0587:                    }
0588:                }
0589:
0590:                for (Iterator iter = currentSteps.iterator(); !validAction
0591:                        && iter.hasNext();) {
0592:                    Step step = (Step) iter.next();
0593:                    StepDescriptor s = wf.getStep(step.getStepId());
0594:
0595:                    for (Iterator iterator = s.getActions().iterator(); !validAction
0596:                            && iterator.hasNext();) {
0597:                        ActionDescriptor actionDesc = (ActionDescriptor) iterator
0598:                                .next();
0599:
0600:                        if (actionDesc.getId() == actionId) {
0601:                            action = actionDesc;
0602:
0603:                            if (isActionAvailable(action, transientVars, ps, s
0604:                                    .getId())) {
0605:                                validAction = true;
0606:                            }
0607:                        }
0608:                    }
0609:                }
0610:
0611:                if (!validAction) {
0612:                    throw new InvalidActionException("Action " + actionId
0613:                            + " is invalid");
0614:                }
0615:
0616:                try {
0617:                    //transition the workflow, if it wasn't explicitly finished, check for an implicit finish
0618:                    if (!transitionWorkflow(entry, currentSteps, store, wf,
0619:                            action, transientVars, inputs, ps)) {
0620:                        checkImplicitFinish(action, id);
0621:                    }
0622:                } catch (WorkflowException e) {
0623:                    context.setRollbackOnly();
0624:                    throw e;
0625:                }
0626:            }
0627:
0628:            public void executeTriggerFunction(long id, int triggerId)
0629:                    throws WorkflowException {
0630:                WorkflowStore store = getPersistence();
0631:                WorkflowEntry entry = store.findEntry(id);
0632:
0633:                if (entry == null) {
0634:                    log.warn("Cannot execute trigger #" + triggerId
0635:                            + " on non-existent workflow id#" + id);
0636:
0637:                    return;
0638:                }
0639:
0640:                WorkflowDescriptor wf = getConfiguration().getWorkflow(
0641:                        entry.getWorkflowName());
0642:
0643:                PropertySet ps = store.getPropertySet(id);
0644:                Map transientVars = new HashMap();
0645:                populateTransientMap(entry, transientVars, wf.getRegisters(),
0646:                        null, store.findCurrentSteps(id), ps);
0647:                executeFunction(wf.getTriggerFunction(triggerId),
0648:                        transientVars, ps);
0649:            }
0650:
0651:            public long initialize(String workflowName, int initialAction,
0652:                    Map inputs) throws InvalidRoleException,
0653:                    InvalidInputException, WorkflowException {
0654:                WorkflowDescriptor wf = getConfiguration().getWorkflow(
0655:                        workflowName);
0656:
0657:                WorkflowStore store = getPersistence();
0658:                WorkflowEntry entry = store.createEntry(workflowName);
0659:
0660:                // start with a memory property set, but clone it after we have an ID
0661:                PropertySet ps = store.getPropertySet(entry.getId());
0662:                Map transientVars = new HashMap();
0663:
0664:                if (inputs != null) {
0665:                    transientVars.putAll(inputs);
0666:                }
0667:
0668:                populateTransientMap(entry, transientVars, wf.getRegisters(),
0669:                        new Integer(initialAction), Collections.EMPTY_LIST, ps);
0670:
0671:                if (!canInitialize(workflowName, initialAction, transientVars,
0672:                        ps)) {
0673:                    context.setRollbackOnly();
0674:                    throw new InvalidRoleException(
0675:                            "You are restricted from initializing this workflow");
0676:                }
0677:
0678:                ActionDescriptor action = wf.getInitialAction(initialAction);
0679:
0680:                try {
0681:                    transitionWorkflow(entry, Collections.EMPTY_LIST, store,
0682:                            wf, action, transientVars, inputs, ps);
0683:                } catch (WorkflowException e) {
0684:                    context.setRollbackOnly();
0685:                    throw e;
0686:                }
0687:
0688:                long entryId = entry.getId();
0689:
0690:                // now clone the memory PS to the real PS
0691:                //PropertySetManager.clone(ps, store.getPropertySet(entryId));
0692:                return entryId;
0693:            }
0694:
0695:            /**
0696:             * @ejb.interface-method
0697:             */
0698:            public List query(WorkflowQuery query) throws StoreException {
0699:                return getPersistence().query(query);
0700:            }
0701:
0702:            /**
0703:             * @ejb.interface-method
0704:             */
0705:            public List query(WorkflowExpressionQuery query)
0706:                    throws WorkflowException {
0707:                return getPersistence().query(query);
0708:            }
0709:
0710:            /**
0711:             * @ejb.interface-method
0712:             */
0713:            public boolean removeWorkflowDescriptor(String workflowName)
0714:                    throws FactoryException {
0715:                return getConfiguration().removeWorkflow(workflowName);
0716:            }
0717:
0718:            /**
0719:             * @ejb.interface-method
0720:             */
0721:            public boolean saveWorkflowDescriptor(String workflowName,
0722:                    WorkflowDescriptor descriptor, boolean replace)
0723:                    throws FactoryException {
0724:                boolean success = getConfiguration().saveWorkflow(workflowName,
0725:                        descriptor, replace);
0726:
0727:                return success;
0728:            }
0729:
0730:            protected List getAvailableActionsForStep(WorkflowDescriptor wf,
0731:                    Step step, Map transientVars, PropertySet ps)
0732:                    throws WorkflowException {
0733:                List l = new ArrayList();
0734:                StepDescriptor s = wf.getStep(step.getStepId());
0735:
0736:                if (s == null) {
0737:                    log
0738:                            .warn("getAvailableActionsForStep called for non-existent step Id #"
0739:                                    + step.getStepId());
0740:
0741:                    return l;
0742:                }
0743:
0744:                List actions = s.getActions();
0745:
0746:                if ((actions == null) || (actions.size() == 0)) {
0747:                    return l;
0748:                }
0749:
0750:                for (Iterator iterator2 = actions.iterator(); iterator2
0751:                        .hasNext();) {
0752:                    ActionDescriptor action = (ActionDescriptor) iterator2
0753:                            .next();
0754:                    RestrictionDescriptor restriction = action.getRestriction();
0755:                    ConditionsDescriptor conditions = null;
0756:
0757:                    transientVars.put("actionId", new Integer(action.getId()));
0758:
0759:                    if (restriction != null) {
0760:                        conditions = restriction.getConditionsDescriptor();
0761:                    }
0762:
0763:                    if (passesConditions(wf.getGlobalConditions(), new HashMap(
0764:                            transientVars), ps, s.getId())
0765:                            && passesConditions(conditions, new HashMap(
0766:                                    transientVars), ps, s.getId())) {
0767:                        l.add(new Integer(action.getId()));
0768:                    }
0769:                }
0770:
0771:                return l;
0772:            }
0773:
0774:            protected int[] getAvailableAutoActions(long id, Map inputs) {
0775:                try {
0776:                    WorkflowStore store = getPersistence();
0777:                    WorkflowEntry entry = store.findEntry(id);
0778:
0779:                    if (entry == null) {
0780:                        throw new IllegalArgumentException(
0781:                                "No such workflow id " + id);
0782:                    }
0783:
0784:                    if (entry.getState() != WorkflowEntry.ACTIVATED) {
0785:                        log.debug("--> state is " + entry.getState());
0786:
0787:                        return new int[0];
0788:                    }
0789:
0790:                    WorkflowDescriptor wf = getConfiguration().getWorkflow(
0791:                            entry.getWorkflowName());
0792:
0793:                    if (wf == null) {
0794:                        throw new IllegalArgumentException("No such workflow "
0795:                                + entry.getWorkflowName());
0796:                    }
0797:
0798:                    List l = new ArrayList();
0799:                    PropertySet ps = store.getPropertySet(id);
0800:                    Map transientVars = (inputs == null) ? new HashMap()
0801:                            : new HashMap(inputs);
0802:                    Collection currentSteps = store.findCurrentSteps(id);
0803:
0804:                    populateTransientMap(entry, transientVars, wf
0805:                            .getRegisters(), new Integer(0), currentSteps, ps);
0806:
0807:                    // get global actions
0808:                    List globalActions = wf.getGlobalActions();
0809:
0810:                    for (Iterator iterator = globalActions.iterator(); iterator
0811:                            .hasNext();) {
0812:                        ActionDescriptor action = (ActionDescriptor) iterator
0813:                                .next();
0814:
0815:                        transientVars.put("actionId", new Integer(action
0816:                                .getId()));
0817:
0818:                        if (action.getAutoExecute()) {
0819:                            if (isActionAvailable(action, transientVars, ps, 0)) {
0820:                                l.add(new Integer(action.getId()));
0821:                            }
0822:                        }
0823:                    }
0824:
0825:                    // get normal actions
0826:                    for (Iterator iterator = currentSteps.iterator(); iterator
0827:                            .hasNext();) {
0828:                        Step step = (Step) iterator.next();
0829:                        l.addAll(getAvailableAutoActionsForStep(wf, step,
0830:                                transientVars, ps));
0831:                    }
0832:
0833:                    int[] actions = new int[l.size()];
0834:
0835:                    for (int i = 0; i < actions.length; i++) {
0836:                        actions[i] = ((Integer) l.get(i)).intValue();
0837:                    }
0838:
0839:                    return actions;
0840:                } catch (Exception e) {
0841:                    log.error("Error checking available actions", e);
0842:
0843:                    return new int[0];
0844:                }
0845:            }
0846:
0847:            /**
0848:             * Get just auto action availables for a step
0849:             */
0850:            protected List getAvailableAutoActionsForStep(
0851:                    WorkflowDescriptor wf, Step step, Map transientVars,
0852:                    PropertySet ps) throws WorkflowException {
0853:                List l = new ArrayList();
0854:                StepDescriptor s = wf.getStep(step.getStepId());
0855:
0856:                if (s == null) {
0857:                    log
0858:                            .warn("getAvailableAutoActionsForStep called for non-existent step Id #"
0859:                                    + step.getStepId());
0860:
0861:                    return l;
0862:                }
0863:
0864:                List actions = s.getActions();
0865:
0866:                if ((actions == null) || (actions.size() == 0)) {
0867:                    return l;
0868:                }
0869:
0870:                for (Iterator iterator2 = actions.iterator(); iterator2
0871:                        .hasNext();) {
0872:                    ActionDescriptor action = (ActionDescriptor) iterator2
0873:                            .next();
0874:
0875:                    transientVars.put("actionId", new Integer(action.getId()));
0876:
0877:                    //check auto
0878:                    if (action.getAutoExecute()) {
0879:                        if (isActionAvailable(action, transientVars, ps, s
0880:                                .getId())) {
0881:                            l.add(new Integer(action.getId()));
0882:                        }
0883:                    }
0884:                }
0885:
0886:                return l;
0887:            }
0888:
0889:            protected WorkflowStore getPersistence() throws StoreException {
0890:                return getConfiguration().getWorkflowStore();
0891:            }
0892:
0893:            protected void checkImplicitFinish(ActionDescriptor action, long id)
0894:                    throws WorkflowException {
0895:                WorkflowStore store = getPersistence();
0896:                WorkflowEntry entry = store.findEntry(id);
0897:
0898:                WorkflowDescriptor wf = getConfiguration().getWorkflow(
0899:                        entry.getWorkflowName());
0900:
0901:                Collection currentSteps = store.findCurrentSteps(id);
0902:
0903:                boolean isCompleted = true;
0904:
0905:                for (Iterator iterator = currentSteps.iterator(); iterator
0906:                        .hasNext();) {
0907:                    Step step = (Step) iterator.next();
0908:                    StepDescriptor stepDes = wf.getStep(step.getStepId());
0909:
0910:                    // if at least on current step have an available action
0911:                    if (stepDes.getActions().size() > 0) {
0912:                        isCompleted = false;
0913:                    }
0914:                }
0915:
0916:                if (isCompleted) {
0917:                    completeEntry(action, id, currentSteps,
0918:                            WorkflowEntry.COMPLETED);
0919:                }
0920:            }
0921:
0922:            /**
0923:             * Mark the specified entry as completed, and move all current steps to history.
0924:             */
0925:            protected void completeEntry(ActionDescriptor action, long id,
0926:                    Collection currentSteps, int state) throws StoreException {
0927:                getPersistence().setEntryState(id, state);
0928:
0929:                Iterator i = new ArrayList(currentSteps).iterator();
0930:
0931:                while (i.hasNext()) {
0932:                    Step step = (Step) i.next();
0933:                    String oldStatus = (action != null) ? action
0934:                            .getUnconditionalResult().getOldStatus()
0935:                            : "Finished";
0936:                    getPersistence().markFinished(step,
0937:                            (action != null) ? action.getId() : (-1),
0938:                            new Date(), oldStatus, context.getCaller());
0939:                    getPersistence().moveToHistory(step);
0940:                }
0941:            }
0942:
0943:            /**
0944:             * Executes a function.
0945:             *
0946:             * @param function the function to execute
0947:             * @param transientVars the transientVars given by the end-user
0948:             * @param ps the persistence variables
0949:             */
0950:            protected void executeFunction(FunctionDescriptor function,
0951:                    Map transientVars, PropertySet ps) throws WorkflowException {
0952:                if (function != null) {
0953:                    String type = function.getType();
0954:
0955:                    Map args = new HashMap(function.getArgs());
0956:
0957:                    for (Iterator iterator = args.entrySet().iterator(); iterator
0958:                            .hasNext();) {
0959:                        Map.Entry mapEntry = (Map.Entry) iterator.next();
0960:                        mapEntry.setValue(getConfiguration()
0961:                                .getVariableResolver().translateVariables(
0962:                                        (String) mapEntry.getValue(),
0963:                                        transientVars, ps));
0964:                    }
0965:
0966:                    FunctionProvider provider = getResolver().getFunction(type,
0967:                            args);
0968:
0969:                    if (provider == null) {
0970:                        String message = "Could not load FunctionProvider class";
0971:                        context.setRollbackOnly();
0972:                        throw new WorkflowException(message);
0973:                    }
0974:
0975:                    try {
0976:                        provider.execute(transientVars, args, ps);
0977:                    } catch (WorkflowException e) {
0978:                        context.setRollbackOnly();
0979:                        throw e;
0980:                    }
0981:                }
0982:            }
0983:
0984:            protected boolean passesCondition(
0985:                    ConditionDescriptor conditionDesc, Map transientVars,
0986:                    PropertySet ps, int currentStepId) throws WorkflowException {
0987:                String type = conditionDesc.getType();
0988:
0989:                Map args = new HashMap(conditionDesc.getArgs());
0990:
0991:                for (Iterator iterator = args.entrySet().iterator(); iterator
0992:                        .hasNext();) {
0993:                    Map.Entry mapEntry = (Map.Entry) iterator.next();
0994:                    mapEntry.setValue(getConfiguration().getVariableResolver()
0995:                            .translateVariables((String) mapEntry.getValue(),
0996:                                    transientVars, ps));
0997:                }
0998:
0999:                if (currentStepId != -1) {
1000:                    Object stepId = args.get("stepId");
1001:
1002:                    if ((stepId != null) && stepId.equals("-1")) {
1003:                        args.put("stepId", String.valueOf(currentStepId));
1004:                    }
1005:                }
1006:
1007:                Condition condition = getResolver().getCondition(type, args);
1008:
1009:                if (condition == null) {
1010:                    context.setRollbackOnly();
1011:                    throw new WorkflowException("Could not load condition");
1012:                }
1013:
1014:                try {
1015:                    boolean passed = condition.passesCondition(transientVars,
1016:                            args, ps);
1017:
1018:                    if (conditionDesc.isNegate()) {
1019:                        passed = !passed;
1020:                    }
1021:
1022:                    return passed;
1023:                } catch (Exception e) {
1024:                    context.setRollbackOnly();
1025:
1026:                    if (e instanceof  WorkflowException) {
1027:                        throw (WorkflowException) e;
1028:                    }
1029:
1030:                    throw new WorkflowException(
1031:                            "Unknown exception encountered when checking condition "
1032:                                    + condition, e);
1033:                }
1034:            }
1035:
1036:            protected boolean passesConditions(String conditionType,
1037:                    List conditions, Map transientVars, PropertySet ps,
1038:                    int currentStepId) throws WorkflowException {
1039:                if ((conditions == null) || (conditions.size() == 0)) {
1040:                    return true;
1041:                }
1042:
1043:                boolean and = "AND".equals(conditionType);
1044:                boolean or = !and;
1045:
1046:                for (Iterator iterator = conditions.iterator(); iterator
1047:                        .hasNext();) {
1048:                    AbstractDescriptor descriptor = (AbstractDescriptor) iterator
1049:                            .next();
1050:                    boolean result;
1051:
1052:                    if (descriptor instanceof  ConditionsDescriptor) {
1053:                        ConditionsDescriptor conditionsDescriptor = (ConditionsDescriptor) descriptor;
1054:                        result = passesConditions(conditionsDescriptor
1055:                                .getType(), conditionsDescriptor
1056:                                .getConditions(), transientVars, ps,
1057:                                currentStepId);
1058:                    } else {
1059:                        result = passesCondition(
1060:                                (ConditionDescriptor) descriptor,
1061:                                transientVars, ps, currentStepId);
1062:                    }
1063:
1064:                    if (and && !result) {
1065:                        return false;
1066:                    } else if (or && result) {
1067:                        return true;
1068:                    }
1069:                }
1070:
1071:                if (and) {
1072:                    return true;
1073:                } else if (or) {
1074:                    return false;
1075:                } else {
1076:                    return false;
1077:                }
1078:            }
1079:
1080:            protected boolean passesConditions(ConditionsDescriptor descriptor,
1081:                    Map transientVars, PropertySet ps, int currentStepId)
1082:                    throws WorkflowException {
1083:                if (descriptor == null) {
1084:                    return true;
1085:                }
1086:
1087:                return passesConditions(descriptor.getType(), descriptor
1088:                        .getConditions(), transientVars, ps, currentStepId);
1089:            }
1090:
1091:            protected void populateTransientMap(WorkflowEntry entry,
1092:                    Map transientVars, List registers, Integer actionId,
1093:                    Collection currentSteps, PropertySet ps)
1094:                    throws WorkflowException {
1095:                transientVars.put("context", context);
1096:                transientVars.put("entry", entry);
1097:                transientVars.put("store", getPersistence());
1098:                transientVars.put("configuration", getConfiguration());
1099:                transientVars.put("descriptor", getConfiguration().getWorkflow(
1100:                        entry.getWorkflowName()));
1101:
1102:                if (actionId != null) {
1103:                    transientVars.put("actionId", actionId);
1104:                }
1105:
1106:                transientVars.put("currentSteps", new ArrayList(currentSteps));
1107:
1108:                // now talk to the registers for any extra objects needed in scope
1109:                for (Iterator iterator = registers.iterator(); iterator
1110:                        .hasNext();) {
1111:                    RegisterDescriptor register = (RegisterDescriptor) iterator
1112:                            .next();
1113:                    Map args = register.getArgs();
1114:
1115:                    String type = register.getType();
1116:                    Register r = getResolver().getRegister(type, args);
1117:
1118:                    if (r == null) {
1119:                        String message = "Could not load register class";
1120:                        context.setRollbackOnly();
1121:                        throw new WorkflowException(message);
1122:                    }
1123:
1124:                    try {
1125:                        transientVars.put(register.getVariableName(), r
1126:                                .registerVariable(context, entry, args, ps));
1127:                    } catch (Exception e) {
1128:                        context.setRollbackOnly();
1129:
1130:                        if (e instanceof  WorkflowException) {
1131:                            throw (WorkflowException) e;
1132:                        }
1133:
1134:                        throw new WorkflowException(
1135:                                "An unknown exception occured while registering variable using register "
1136:                                        + r, e);
1137:                    }
1138:                }
1139:            }
1140:
1141:            /**
1142:             * @return true if the instance has been explicitly completed is this transition, false otherwise
1143:             * @throws WorkflowException
1144:             */
1145:            protected boolean transitionWorkflow(WorkflowEntry entry,
1146:                    List currentSteps, WorkflowStore store,
1147:                    WorkflowDescriptor wf, ActionDescriptor action,
1148:                    Map transientVars, Map inputs, PropertySet ps)
1149:                    throws WorkflowException {
1150:                Map cache = (Map) stateCache.get();
1151:
1152:                if (cache != null) {
1153:                    cache.clear();
1154:                } else {
1155:                    stateCache.set(new HashMap());
1156:                }
1157:
1158:                Step step = getCurrentStep(wf, action.getId(), currentSteps,
1159:                        transientVars, ps);
1160:
1161:                if (action.getValidators().size() > 0) {
1162:                    verifyInputs(entry, action.getValidators(), Collections
1163:                            .unmodifiableMap(transientVars), ps);
1164:                }
1165:
1166:                //we're leaving the current step, so let's execute its post-functions
1167:                //check if we actually have a current step
1168:                if (step != null) {
1169:                    List stepPostFunctions = wf.getStep(step.getStepId())
1170:                            .getPostFunctions();
1171:
1172:                    for (Iterator iterator = stepPostFunctions.iterator(); iterator
1173:                            .hasNext();) {
1174:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1175:                                .next();
1176:                        executeFunction(function, transientVars, ps);
1177:                    }
1178:                }
1179:
1180:                // preFunctions
1181:                List preFunctions = action.getPreFunctions();
1182:
1183:                for (Iterator iterator = preFunctions.iterator(); iterator
1184:                        .hasNext();) {
1185:                    FunctionDescriptor function = (FunctionDescriptor) iterator
1186:                            .next();
1187:                    executeFunction(function, transientVars, ps);
1188:                }
1189:
1190:                // check each conditional result
1191:                List conditionalResults = action.getConditionalResults();
1192:                List extraPreFunctions = null;
1193:                List extraPostFunctions = null;
1194:                ResultDescriptor[] theResults = new ResultDescriptor[1];
1195:
1196:                for (Iterator iterator = conditionalResults.iterator(); iterator
1197:                        .hasNext();) {
1198:                    ConditionalResultDescriptor conditionalResult = (ConditionalResultDescriptor) iterator
1199:                            .next();
1200:
1201:                    if (passesConditions(null, conditionalResult
1202:                            .getConditions(), Collections
1203:                            .unmodifiableMap(transientVars), ps,
1204:                            (step != null) ? step.getStepId() : (-1))) {
1205:                        //if (evaluateExpression(conditionalResult.getCondition(), entry, wf.getRegisters(), null, transientVars)) {
1206:                        theResults[0] = conditionalResult;
1207:
1208:                        if (conditionalResult.getValidators().size() > 0) {
1209:                            verifyInputs(entry, conditionalResult
1210:                                    .getValidators(), Collections
1211:                                    .unmodifiableMap(transientVars), ps);
1212:                        }
1213:
1214:                        extraPreFunctions = conditionalResult.getPreFunctions();
1215:                        extraPostFunctions = conditionalResult
1216:                                .getPostFunctions();
1217:
1218:                        break;
1219:                    }
1220:                }
1221:
1222:                // use unconditional-result if a condition hasn't been met
1223:                if (theResults[0] == null) {
1224:                    theResults[0] = action.getUnconditionalResult();
1225:                    verifyInputs(entry, theResults[0].getValidators(),
1226:                            Collections.unmodifiableMap(transientVars), ps);
1227:                    extraPreFunctions = theResults[0].getPreFunctions();
1228:                    extraPostFunctions = theResults[0].getPostFunctions();
1229:                }
1230:
1231:                if (log.isDebugEnabled()) {
1232:                    log.debug("theResult=" + theResults[0].getStep() + ' '
1233:                            + theResults[0].getStatus());
1234:                }
1235:
1236:                if ((extraPreFunctions != null)
1237:                        && (extraPreFunctions.size() > 0)) {
1238:                    // run any extra pre-functions that haven't been run already
1239:                    for (Iterator iterator = extraPreFunctions.iterator(); iterator
1240:                            .hasNext();) {
1241:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1242:                                .next();
1243:                        executeFunction(function, transientVars, ps);
1244:                    }
1245:                }
1246:
1247:                // go to next step
1248:                if (theResults[0].getSplit() != 0) {
1249:                    // the result is a split request, handle it correctly
1250:                    SplitDescriptor splitDesc = wf.getSplit(theResults[0]
1251:                            .getSplit());
1252:                    Collection results = splitDesc.getResults();
1253:                    List splitPreFunctions = new ArrayList();
1254:                    List splitPostFunctions = new ArrayList();
1255:
1256:                    //check all results in the split and verify the input against any validators specified
1257:                    //also build up all the pre and post functions that should be called.
1258:                    for (Iterator iterator = results.iterator(); iterator
1259:                            .hasNext();) {
1260:                        ResultDescriptor resultDescriptor = (ResultDescriptor) iterator
1261:                                .next();
1262:
1263:                        if (resultDescriptor.getValidators().size() > 0) {
1264:                            verifyInputs(entry, resultDescriptor
1265:                                    .getValidators(), Collections
1266:                                    .unmodifiableMap(transientVars), ps);
1267:                        }
1268:
1269:                        splitPreFunctions.addAll(resultDescriptor
1270:                                .getPreFunctions());
1271:                        splitPostFunctions.addAll(resultDescriptor
1272:                                .getPostFunctions());
1273:                    }
1274:
1275:                    // now execute the pre-functions
1276:                    for (Iterator iterator = splitPreFunctions.iterator(); iterator
1277:                            .hasNext();) {
1278:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1279:                                .next();
1280:                        executeFunction(function, transientVars, ps);
1281:                    }
1282:
1283:                    if (!action.isFinish()) {
1284:                        // now make these steps...
1285:                        boolean moveFirst = true;
1286:
1287:                        theResults = new ResultDescriptor[results.size()];
1288:                        results.toArray(theResults);
1289:
1290:                        for (Iterator iterator = results.iterator(); iterator
1291:                                .hasNext();) {
1292:                            ResultDescriptor resultDescriptor = (ResultDescriptor) iterator
1293:                                    .next();
1294:                            Step moveToHistoryStep = null;
1295:
1296:                            if (moveFirst) {
1297:                                moveToHistoryStep = step;
1298:                            }
1299:
1300:                            long[] previousIds = null;
1301:
1302:                            if (step != null) {
1303:                                previousIds = new long[] { step.getId() };
1304:                            }
1305:
1306:                            createNewCurrentStep(resultDescriptor, entry,
1307:                                    store, action.getId(), moveToHistoryStep,
1308:                                    previousIds, transientVars, ps);
1309:                            moveFirst = false;
1310:                        }
1311:                    }
1312:
1313:                    // now execute the post-functions
1314:                    for (Iterator iterator = splitPostFunctions.iterator(); iterator
1315:                            .hasNext();) {
1316:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1317:                                .next();
1318:                        executeFunction(function, transientVars, ps);
1319:                    }
1320:                } else if (theResults[0].getJoin() != 0) {
1321:                    // this is a join, finish this step...
1322:                    JoinDescriptor joinDesc = wf.getJoin(theResults[0]
1323:                            .getJoin());
1324:                    step = store.markFinished(step, action.getId(), new Date(),
1325:                            theResults[0].getOldStatus(), context.getCaller());
1326:                    store.moveToHistory(step);
1327:
1328:                    // ... now check to see if the expression evaluates
1329:                    // (get only current steps that have a result to this join)
1330:                    Collection joinSteps = new ArrayList();
1331:                    joinSteps.add(step);
1332:
1333:                    //currentSteps = store.findCurrentSteps(id); // shouldn't need to refresh the list
1334:                    for (Iterator iterator = currentSteps.iterator(); iterator
1335:                            .hasNext();) {
1336:                        Step currentStep = (Step) iterator.next();
1337:
1338:                        if (currentStep.getId() != step.getId()) {
1339:                            StepDescriptor stepDesc = wf.getStep(currentStep
1340:                                    .getStepId());
1341:
1342:                            if (stepDesc.resultsInJoin(theResults[0].getJoin())) {
1343:                                joinSteps.add(currentStep);
1344:                            }
1345:                        }
1346:                    }
1347:
1348:                    //we also need to check history steps that were finished before this one
1349:                    //that might be part of the join
1350:                    List historySteps = store.findHistorySteps(entry.getId());
1351:
1352:                    for (Iterator i = historySteps.iterator(); i.hasNext();) {
1353:                        Step historyStep = (Step) i.next();
1354:
1355:                        if (historyStep.getId() != step.getId()) {
1356:                            StepDescriptor stepDesc = wf.getStep(historyStep
1357:                                    .getStepId());
1358:
1359:                            if (stepDesc.resultsInJoin(theResults[0].getJoin())) {
1360:                                joinSteps.add(historyStep);
1361:                            }
1362:                        }
1363:                    }
1364:
1365:                    JoinNodes jn = new JoinNodes(joinSteps);
1366:                    transientVars.put("jn", jn);
1367:
1368:                    //todo verify that 0 is the right value for currentstep here
1369:                    if (passesConditions(null, joinDesc.getConditions(),
1370:                            Collections.unmodifiableMap(transientVars), ps, 0)) {
1371:                        // move the rest without creating a new step ...
1372:                        ResultDescriptor joinresult = joinDesc.getResult();
1373:
1374:                        if (joinresult.getValidators().size() > 0) {
1375:                            verifyInputs(entry, joinresult.getValidators(),
1376:                                    Collections.unmodifiableMap(transientVars),
1377:                                    ps);
1378:                        }
1379:
1380:                        // now execute the pre-functions
1381:                        for (Iterator iterator = joinresult.getPreFunctions()
1382:                                .iterator(); iterator.hasNext();) {
1383:                            FunctionDescriptor function = (FunctionDescriptor) iterator
1384:                                    .next();
1385:                            executeFunction(function, transientVars, ps);
1386:                        }
1387:
1388:                        long[] previousIds = new long[joinSteps.size()];
1389:                        int i = 1;
1390:
1391:                        for (Iterator iterator = joinSteps.iterator(); iterator
1392:                                .hasNext();) {
1393:                            Step currentStep = (Step) iterator.next();
1394:
1395:                            if (currentStep.getId() != step.getId()) {
1396:                                //if this is already a history step (eg, for all join steps completed prior to this one),
1397:                                //we don't move it, since it's already history.
1398:                                if (!historySteps.contains(currentStep)) {
1399:                                    store.moveToHistory(currentStep);
1400:                                }
1401:
1402:                                previousIds[i] = currentStep.getId();
1403:                                i++;
1404:                            }
1405:                        }
1406:
1407:                        if (!action.isFinish()) {
1408:                            // ... now finish this step normally
1409:                            previousIds[0] = step.getId();
1410:                            theResults[0] = joinDesc.getResult();
1411:
1412:                            //we pass in null for the current step since we've already moved it to history above
1413:                            createNewCurrentStep(joinDesc.getResult(), entry,
1414:                                    store, action.getId(), null, previousIds,
1415:                                    transientVars, ps);
1416:                        }
1417:
1418:                        // now execute the post-functions
1419:                        for (Iterator iterator = joinresult.getPostFunctions()
1420:                                .iterator(); iterator.hasNext();) {
1421:                            FunctionDescriptor function = (FunctionDescriptor) iterator
1422:                                    .next();
1423:                            executeFunction(function, transientVars, ps);
1424:                        }
1425:                    }
1426:                } else {
1427:                    // normal finish, no splits or joins
1428:                    long[] previousIds = null;
1429:
1430:                    if (step != null) {
1431:                        previousIds = new long[] { step.getId() };
1432:                    }
1433:
1434:                    if (!action.isFinish()) {
1435:                        createNewCurrentStep(theResults[0], entry, store,
1436:                                action.getId(), step, previousIds,
1437:                                transientVars, ps);
1438:                    }
1439:                }
1440:
1441:                // postFunctions (BOTH)
1442:                if (extraPostFunctions != null) {
1443:                    for (Iterator iterator = extraPostFunctions.iterator(); iterator
1444:                            .hasNext();) {
1445:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1446:                                .next();
1447:                        executeFunction(function, transientVars, ps);
1448:                    }
1449:                }
1450:
1451:                List postFunctions = action.getPostFunctions();
1452:
1453:                for (Iterator iterator = postFunctions.iterator(); iterator
1454:                        .hasNext();) {
1455:                    FunctionDescriptor function = (FunctionDescriptor) iterator
1456:                            .next();
1457:                    executeFunction(function, transientVars, ps);
1458:                }
1459:
1460:                //if executed action was an initial action then workflow is activated
1461:                if ((wf.getInitialAction(action.getId()) != null)
1462:                        && (entry.getState() != WorkflowEntry.ACTIVATED)) {
1463:                    changeEntryState(entry.getId(), WorkflowEntry.ACTIVATED);
1464:                }
1465:
1466:                //if it's a finish action, then we halt
1467:                if (action.isFinish()) {
1468:                    completeEntry(action, entry.getId(), getCurrentSteps(entry
1469:                            .getId()), WorkflowEntry.COMPLETED);
1470:
1471:                    return true;
1472:                }
1473:
1474:                //get available autoexec actions
1475:                int[] availableAutoActions = getAvailableAutoActions(entry
1476:                        .getId(), inputs);
1477:
1478:                //we perform the first autoaction that applies, not all of them.
1479:                if (availableAutoActions.length > 0) {
1480:                    doAction(entry.getId(), availableAutoActions[0], inputs);
1481:                }
1482:
1483:                return false;
1484:            }
1485:
1486:            /**
1487:             * Validates input against a list of ValidatorDescriptor objects.
1488:             *
1489:             * @param entry the workflow instance
1490:             * @param validators the list of ValidatorDescriptors
1491:             * @param transientVars the transientVars
1492:             * @param ps the persistence variables
1493:             * @throws InvalidInputException if the input is deemed invalid by any validator
1494:             */
1495:            protected void verifyInputs(WorkflowEntry entry, List validators,
1496:                    Map transientVars, PropertySet ps) throws WorkflowException {
1497:                for (Iterator iterator = validators.iterator(); iterator
1498:                        .hasNext();) {
1499:                    ValidatorDescriptor input = (ValidatorDescriptor) iterator
1500:                            .next();
1501:
1502:                    if (input != null) {
1503:                        String type = input.getType();
1504:                        HashMap args = new HashMap(input.getArgs());
1505:
1506:                        for (Iterator iterator2 = args.entrySet().iterator(); iterator2
1507:                                .hasNext();) {
1508:                            Map.Entry mapEntry = (Map.Entry) iterator2.next();
1509:                            mapEntry.setValue(getConfiguration()
1510:                                    .getVariableResolver().translateVariables(
1511:                                            (String) mapEntry.getValue(),
1512:                                            transientVars, ps));
1513:                        }
1514:
1515:                        Validator validator = getResolver().getValidator(type,
1516:                                args);
1517:
1518:                        if (validator == null) {
1519:                            String message = "Could not load validator class";
1520:                            context.setRollbackOnly();
1521:                            throw new WorkflowException(message);
1522:                        }
1523:
1524:                        try {
1525:                            validator.validate(transientVars, args, ps);
1526:                        } catch (InvalidInputException e) {
1527:                            throw e;
1528:                        } catch (Exception e) {
1529:                            context.setRollbackOnly();
1530:
1531:                            if (e instanceof  WorkflowException) {
1532:                                throw (WorkflowException) e;
1533:                            }
1534:
1535:                            String message = "An unknown exception occured executing Validator "
1536:                                    + validator;
1537:                            throw new WorkflowException(message, e);
1538:                        }
1539:                    }
1540:                }
1541:            }
1542:
1543:            /**
1544:             * check if an action is available or not
1545:             * @param action The action descriptor
1546:             * @return true if the action is available
1547:             */
1548:            private boolean isActionAvailable(ActionDescriptor action,
1549:                    Map transientVars, PropertySet ps, int stepId)
1550:                    throws WorkflowException {
1551:                if (action == null) {
1552:                    return false;
1553:                }
1554:
1555:                WorkflowDescriptor wf = getWorkflowDescriptorForAction(action);
1556:
1557:                Map cache = (Map) stateCache.get();
1558:
1559:                Boolean result = null;
1560:
1561:                if (cache != null) {
1562:                    result = (Boolean) cache.get(action);
1563:                } else {
1564:                    cache = new HashMap();
1565:                    stateCache.set(cache);
1566:                }
1567:
1568:                if (result == null) {
1569:                    RestrictionDescriptor restriction = action.getRestriction();
1570:                    ConditionsDescriptor conditions = null;
1571:
1572:                    if (restriction != null) {
1573:                        conditions = restriction.getConditionsDescriptor();
1574:                    }
1575:
1576:                    result = new Boolean(passesConditions(wf
1577:                            .getGlobalConditions(), new HashMap(transientVars),
1578:                            ps, stepId)
1579:                            && passesConditions(conditions, new HashMap(
1580:                                    transientVars), ps, stepId));
1581:                    cache.put(action, result);
1582:                }
1583:
1584:                return result.booleanValue();
1585:            }
1586:
1587:            private Step getCurrentStep(WorkflowDescriptor wfDesc,
1588:                    int actionId, List currentSteps, Map transientVars,
1589:                    PropertySet ps) throws WorkflowException {
1590:                if (currentSteps.size() == 1) {
1591:                    return (Step) currentSteps.get(0);
1592:                }
1593:
1594:                for (Iterator iterator = currentSteps.iterator(); iterator
1595:                        .hasNext();) {
1596:                    Step step = (Step) iterator.next();
1597:                    ActionDescriptor action = wfDesc.getStep(step.getStepId())
1598:                            .getAction(actionId);
1599:
1600:                    //$AR init
1601:                    if (isActionAvailable(action, transientVars, ps, step
1602:                            .getStepId())) {
1603:                        return step;
1604:                    }
1605:
1606:                    //$AR end
1607:                }
1608:
1609:                return null;
1610:            }
1611:
1612:            private WorkflowDescriptor getWorkflowDescriptorForAction(
1613:                    ActionDescriptor action) {
1614:                AbstractDescriptor objWfd = action;
1615:
1616:                while (!(objWfd instanceof  WorkflowDescriptor)) {
1617:                    objWfd = objWfd.getParent();
1618:                }
1619:
1620:                WorkflowDescriptor wf = (WorkflowDescriptor) objWfd;
1621:
1622:                return wf;
1623:            }
1624:
1625:            private boolean canInitialize(String workflowName,
1626:                    int initialAction, Map transientVars, PropertySet ps)
1627:                    throws WorkflowException {
1628:                WorkflowDescriptor wf = getConfiguration().getWorkflow(
1629:                        workflowName);
1630:
1631:                ActionDescriptor actionDescriptor = wf
1632:                        .getInitialAction(initialAction);
1633:
1634:                if (actionDescriptor == null) {
1635:                    throw new InvalidActionException("Invalid Initial Action #"
1636:                            + initialAction);
1637:                }
1638:
1639:                RestrictionDescriptor restriction = actionDescriptor
1640:                        .getRestriction();
1641:                ConditionsDescriptor conditions = null;
1642:
1643:                if (restriction != null) {
1644:                    conditions = restriction.getConditionsDescriptor();
1645:                }
1646:
1647:                return passesConditions(conditions, new HashMap(transientVars),
1648:                        ps, 0);
1649:            }
1650:
1651:            private Step createNewCurrentStep(ResultDescriptor theResult,
1652:                    WorkflowEntry entry, WorkflowStore store, int actionId,
1653:                    Step currentStep, long[] previousIds, Map transientVars,
1654:                    PropertySet ps) throws WorkflowException {
1655:                try {
1656:                    int nextStep = theResult.getStep();
1657:
1658:                    if (nextStep == -1) {
1659:                        if (currentStep != null) {
1660:                            nextStep = currentStep.getStepId();
1661:                        } else {
1662:                            throw new StoreException(
1663:                                    "Illegal argument: requested new current step same as current step, but current step not specified");
1664:                        }
1665:                    }
1666:
1667:                    if (log.isDebugEnabled()) {
1668:                        log.debug("Outcome: stepId="
1669:                                + nextStep
1670:                                + ", status="
1671:                                + theResult.getStatus()
1672:                                + ", owner="
1673:                                + theResult.getOwner()
1674:                                + ", actionId="
1675:                                + actionId
1676:                                + ", currentStep="
1677:                                + ((currentStep != null) ? currentStep
1678:                                        .getStepId() : 0));
1679:                    }
1680:
1681:                    if (previousIds == null) {
1682:                        previousIds = new long[0];
1683:                    }
1684:
1685:                    String owner = theResult.getOwner();
1686:
1687:                    VariableResolver variableResolver = getConfiguration()
1688:                            .getVariableResolver();
1689:
1690:                    if (owner != null) {
1691:                        Object o = variableResolver.translateVariables(owner,
1692:                                transientVars, ps);
1693:                        owner = (o != null) ? o.toString() : null;
1694:                    }
1695:
1696:                    String oldStatus = theResult.getOldStatus();
1697:                    oldStatus = variableResolver.translateVariables(oldStatus,
1698:                            transientVars, ps).toString();
1699:
1700:                    String status = theResult.getStatus();
1701:                    status = variableResolver.translateVariables(status,
1702:                            transientVars, ps).toString();
1703:
1704:                    if (currentStep != null) {
1705:                        store.markFinished(currentStep, actionId, new Date(),
1706:                                oldStatus, context.getCaller());
1707:                        store.moveToHistory(currentStep);
1708:
1709:                        //store.moveToHistory(actionId, new Date(), currentStep, oldStatus, context.getCaller());
1710:                    }
1711:
1712:                    // construct the start date and optional due date
1713:                    Date startDate = new Date();
1714:                    Date dueDate = null;
1715:
1716:                    if ((theResult.getDueDate() != null)
1717:                            && (theResult.getDueDate().length() > 0)) {
1718:                        Object dueDateObject = variableResolver
1719:                                .translateVariables(theResult.getDueDate(),
1720:                                        transientVars, ps);
1721:
1722:                        if (dueDateObject instanceof  Date) {
1723:                            dueDate = (Date) dueDateObject;
1724:                        } else if (dueDateObject instanceof  String) {
1725:                            long offset = 0;
1726:
1727:                            try {
1728:                                offset = Long.parseLong((String) dueDateObject);
1729:                            } catch (NumberFormatException e) {
1730:                            }
1731:
1732:                            if (offset > 0) {
1733:                                dueDate = new Date(startDate.getTime() + offset);
1734:                            }
1735:                        } else if (dueDateObject instanceof  Number) {
1736:                            Number num = (Number) dueDateObject;
1737:                            long offset = num.longValue();
1738:
1739:                            if (offset > 0) {
1740:                                dueDate = new Date(startDate.getTime() + offset);
1741:                            }
1742:                        }
1743:                    }
1744:
1745:                    Step newStep = store.createCurrentStep(entry.getId(),
1746:                            nextStep, owner, startDate, dueDate, status,
1747:                            previousIds);
1748:                    transientVars.put("createdStep", newStep);
1749:
1750:                    if ((previousIds != null) && (previousIds.length == 0)
1751:                            && (currentStep == null)) {
1752:                        // At this point, it must be a brand new workflow, so we'll overwrite the empty currentSteps
1753:                        // with an array of just this current step
1754:                        List currentSteps = new ArrayList();
1755:                        currentSteps.add(newStep);
1756:                        transientVars.put("currentSteps", new ArrayList(
1757:                                currentSteps));
1758:                    }
1759:
1760:                    WorkflowDescriptor descriptor = (WorkflowDescriptor) transientVars
1761:                            .get("descriptor");
1762:                    StepDescriptor step = descriptor.getStep(nextStep);
1763:
1764:                    if (step == null) {
1765:                        throw new WorkflowException("step #" + nextStep
1766:                                + " does not exist");
1767:                    }
1768:
1769:                    List preFunctions = step.getPreFunctions();
1770:
1771:                    for (Iterator iterator = preFunctions.iterator(); iterator
1772:                            .hasNext();) {
1773:                        FunctionDescriptor function = (FunctionDescriptor) iterator
1774:                                .next();
1775:                        executeFunction(function, transientVars, ps);
1776:                    }
1777:
1778:                    return newStep;
1779:                } catch (WorkflowException e) {
1780:                    context.setRollbackOnly();
1781:                    throw e;
1782:                }
1783:            }
1784:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.