Source Code Cross Referenced for WorkflowEngineUtilities.java in  » Workflow-Engines » obe-1.0 » org » obe » engine » 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 » obe 1.0 » org.obe.engine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*--
0002:
0003:         Copyright (C) 2002-2005 Adrian Price.
0004:         All rights reserved.
0005:
0006:         Redistribution and use in source and binary forms, with or without
0007:         modification, are permitted provided that the following conditions
0008:         are met:
0009:
0010:         1. Redistributions of source code must retain the above copyright
0011:            notice, this list of conditions, and the following disclaimer.
0012:
0013:         2. Redistributions in binary form must reproduce the above copyright
0014:            notice, this list of conditions, and the disclaimer that follows
0015:            these conditions in the documentation and/or other materials
0016:            provided with the distribution.
0017:
0018:         3. The names "OBE" and "Open Business Engine" must not be used to
0019:         	endorse or promote products derived from this software without prior
0020:         	written permission.  For written permission, please contact
0021:         	adrianprice@sourceforge.net.
0022:
0023:         4. Products derived from this software may not be called "OBE" or
0024:         	"Open Business Engine", nor may "OBE" or "Open Business Engine"
0025:         	appear in their name, without prior written permission from
0026:         	Adrian Price (adrianprice@users.sourceforge.net).
0027:
0028:         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0029:         WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0030:         OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0031:         DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
0032:         INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0033:         (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0034:         SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0035:         HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0036:         STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0037:         IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0038:         POSSIBILITY OF SUCH DAMAGE.
0039:
0040:         For more information on OBE, please see
0041:         <http://obe.sourceforge.net/>.
0042:
0043:         */
0044:
0045:        package org.obe.engine;
0046:
0047:        import org.apache.commons.logging.Log;
0048:        import org.apache.commons.logging.LogFactory;
0049:        import org.obe.client.api.model.MIMETypes;
0050:        import org.obe.client.api.model.ProcessInstanceAttributes;
0051:        import org.obe.client.api.repository.*;
0052:        import org.obe.client.api.tool.Parameter;
0053:        import org.obe.client.api.tool.ToolAgent;
0054:        import org.obe.client.api.tool.ToolInvocation;
0055:        import org.obe.client.api.xpdl.InvalidPackageException;
0056:        import org.obe.client.api.xpdl.PackageValidator;
0057:        import org.obe.runtime.tool.NoImplementationToolAgent;
0058:        import org.obe.spi.evaluator.Evaluator;
0059:        import org.obe.spi.evaluator.EvaluatorException;
0060:        import org.obe.spi.event.ApplicationEvent;
0061:        import org.obe.spi.model.*;
0062:        import org.obe.spi.runtime.CompletionStrategy;
0063:        import org.obe.spi.service.*;
0064:        import org.obe.util.ClassUtils;
0065:        import org.obe.util.WorkflowUtilities;
0066:        import org.obe.xpdl.model.activity.*;
0067:        import org.obe.xpdl.model.application.Application;
0068:        import org.obe.xpdl.model.data.*;
0069:        import org.obe.xpdl.model.ext.AssignmentStrategyDef;
0070:        import org.obe.xpdl.model.ext.ToolMode;
0071:        import org.obe.xpdl.model.misc.*;
0072:        import org.obe.xpdl.model.participant.Participant;
0073:        import org.obe.xpdl.model.pkg.XPDLPackage;
0074:        import org.obe.xpdl.model.workflow.ProcessHeader;
0075:        import org.obe.xpdl.model.workflow.WorkflowProcess;
0076:        import org.wfmc.wapi.*;
0077:
0078:        import java.beans.PropertyDescriptor;
0079:        import java.util.*;
0080:
0081:        /**
0082:         * Utility class to support the engine run-time.
0083:         *
0084:         * @author Anthony Eden
0085:         * @author Adrian Price
0086:         */
0087:        public class WorkflowEngineUtilities {
0088:            private static final Log _logger = LogFactory
0089:                    .getLog(WorkflowEngineUtilities.class);
0090:            private static final Comparator _workflowValidityComparator;
0091:            private static final Map _propDescs = new HashMap();
0092:            private static final ToolInvocation[] EMPTY_TOOL_INVOCATIONS = {};
0093:
0094:            public static void validatePackage(XPDLPackage pkg)
0095:                    throws InvalidPackageException {
0096:
0097:                // Unless the package is under development, validate it.
0098:                RedefinableHeader hdr = pkg.getRedefinableHeader();
0099:                if (hdr == null
0100:                        || hdr.getPublicationStatus() != PublicationStatus.UNDER_REVISION) {
0101:
0102:                    PackageValidator validator = new PackageValidator();
0103:                    validator.validate(pkg, true);
0104:                }
0105:            }
0106:
0107:            static {
0108:                _workflowValidityComparator = new Comparator() {
0109:                    // ORDER BY validFrom DESC, validTo DESC, created DESC
0110:                    public int compare(Object o1, Object o2) {
0111:                        ProcessHeader ph1 = ((WorkflowProcess) o1)
0112:                                .getProcessHeader();
0113:                        ProcessHeader ph2 = ((WorkflowProcess) o2)
0114:                                .getProcessHeader();
0115:                        Date d1 = ph1.getValidFrom();
0116:                        Date d2 = ph2.getValidFrom();
0117:                        int order = compareDates(d1, d2);
0118:                        if (order == 0) {
0119:                            d1 = ph1.getValidTo();
0120:                            d2 = ph2.getValidTo();
0121:                            order = compareDates(d1, d2);
0122:                            if (order == 0) {
0123:                                d1 = ph1.getCreated();
0124:                                d2 = ph2.getCreated();
0125:                                order = compareDates(d1, d2);
0126:                            }
0127:                        }
0128:                        return order;
0129:                    }
0130:
0131:                    private int compareDates(Date d1, Date d2) {
0132:                        int order;
0133:                        if (d1 == null && d2 == null) {
0134:                            order = 0;
0135:                        } else if (d1 == null) {
0136:                            order = -1;
0137:                        } else if (d2 == null) {
0138:                            order = +1;
0139:                        } else {
0140:                            order = d1.compareTo(d2);
0141:                        }
0142:                        return order;
0143:                    }
0144:                };
0145:            }
0146:
0147:            public static class AttributeDescription {
0148:                public final String id;
0149:                public final String name;
0150:                public final String description;
0151:                public final DataType dataType;
0152:
0153:                private AttributeDescription(String id, String name,
0154:                        String description, DataType dataType) {
0155:
0156:                    this .id = id;
0157:                    this .name = name;
0158:                    this .description = description;
0159:                    this .dataType = dataType;
0160:                }
0161:            }
0162:
0163:            /**
0164:             * Maps activity state to process state.  When an activity instance with a
0165:             * SubFlow implementation transitions to the <code>newState</code> state,
0166:             * any child process belonging to that activity instance for which it would
0167:             * be a legal transition, should transition to the state returned by this
0168:             * method.
0169:             *
0170:             * @param newState The new process instance state.
0171:             * @return The required activity instance state.
0172:             */
0173:            public static int activityStateToProcessState(int newState) {
0174:                // The states actually have the same ordinals.
0175:                return newState;
0176:            }
0177:
0178:            /**
0179:             * Maps activity state to work item state.  When an activity instance
0180:             * transitions to the <code>newState</code> state, work items belonging
0181:             * to that activity instance and for which it would be a legal transition,
0182:             * should transition to the state returned by this method.
0183:             *
0184:             * @param newState The new activity state.
0185:             * @return The required work item state.
0186:             */
0187:            public static int activityStateToWorkItemState(int newState) {
0188:                // The states actually have the same ordinals.
0189:                return newState;
0190:            }
0191:
0192:            /**
0193:             * Applies the results of a tool invocation to a process instance. INOUT-
0194:             * and OUT-type process variables are updated with the values provided by
0195:             * the application or procedure.  IN-type parameters are ignored.
0196:             *
0197:             * @param parms                      Parameter values returned by the tool invocation.
0198:             * @param processInstance            The process instance to which the values are to be
0199:             *                                   applied.
0200:             * @param ignoreNullSchemaTypeValues <code>true</code> to ignore (i.e.,
0201:             *                                   not store) null values for attributes whose type is defined by an
0202:             *                                   {@link SchemaType XML schema} and which does not map to a
0203:             *                                   {@link BasicType}.  The reason for this is to enable worklist handler
0204:             *                                   clients to support optional file uploads to such attributes.
0205:             * @throws RepositoryException        If the value could not be stored in the
0206:             *                                    attribute.
0207:             * @throws AttributeReadOnlyException If the attribute in question is read-
0208:             *                                    only (applies to most system attributes).
0209:             */
0210:            public static void applyResults(Parameter[] parms,
0211:                    ProcessInstance processInstance,
0212:                    boolean ignoreNullSchemaTypeValues)
0213:                    throws RepositoryException, AttributeReadOnlyException {
0214:
0215:                // Copy the return values into the workflow data.
0216:                for (int i = 0; i < parms.length; i++) {
0217:                    Parameter parm = parms[i];
0218:
0219:                    // Skip input parameters.
0220:                    if (parm.getMode() == ParameterMode.IN)
0221:                        continue;
0222:
0223:                    // Do not clear schema type attributes if an application
0224:                    // returned null - it just means the user didn't upload a file.
0225:                    if (parm.getDataType().getType().getImpliedType().value() == Type.SCHEMA_TYPE
0226:                            && parm.getValue() == null
0227:                            && ignoreNullSchemaTypeValues) {
0228:
0229:                        if (_logger.isDebugEnabled()) {
0230:                            _logger
0231:                                    .debug("Ignoring null value for schema-typed attribute '"
0232:                                            + parm.getId() + '\'');
0233:                        }
0234:
0235:                        continue;
0236:                    }
0237:
0238:                    if (_logger.isDebugEnabled()) {
0239:                        _logger.debug("Updating process attribute '"
0240:                                + parm.getId() + "' with value: "
0241:                                + parm.getValue());
0242:                    }
0243:
0244:                    processInstance.getAttributeInstance(parm.getId())
0245:                            .setValue(Type.DEFAULT_TYPE, parm.getValue());
0246:                }
0247:            }
0248:
0249:            /**
0250:             * Applies data from an application event to a process instance.
0251:             *
0252:             * @param actualParms     The actual parameters passed by the event
0253:             *                        subscription.
0254:             * @param processInstance The process instance to update.
0255:             * @param event           The application event.
0256:             * @param broker          The event broker to use.
0257:             * @throws WMWorkflowException If the event type could not be found or if
0258:             *                             an attribute could not be updated.
0259:             */
0260:            public static void applyResults(ActualParameter[] actualParms,
0261:                    ProcessInstance processInstance, ApplicationEvent event,
0262:                    ApplicationEventBroker broker) throws WMWorkflowException {
0263:
0264:                try {
0265:                    // Extract the parameter values from the inbound event.
0266:                    EventTypeMetaData metaData = broker
0267:                            .findEventTypeMetaData(event.getEventType());
0268:                    FormalParameter[] formalParms = metaData
0269:                            .getFormalParameter();
0270:                    Object[] eventKeys = event.getKeys();
0271:                    Map attrs = processInstance.getAttributeInstances();
0272:                    for (int i = 0, m = formalParms.length, n = actualParms.length; i < n; i++) {
0273:
0274:                        // varargs pattern: reuse the last formal parameter as necessary.
0275:                        FormalParameter formalParm = formalParms[i < m ? i
0276:                                : m - 1];
0277:                        ActualParameter actualParm = actualParms[i];
0278:                        ParameterMode mode = formalParm.getMode();
0279:                        if (mode == ParameterMode.INOUT
0280:                                || mode == ParameterMode.OUT) {
0281:                            String attrName = actualParm.getText();
0282:                            AttributeInstance attr = (AttributeInstance) attrs
0283:                                    .get(attrName);
0284:                            if (attr == null)
0285:                                throw new WMInvalidAttributeException(attrName);
0286:                            attr.setValue(Type.DEFAULT_TYPE, eventKeys[i]);
0287:                        }
0288:                    }
0289:                } catch (RepositoryException e) {
0290:                    throw new WMWorkflowException(e);
0291:                } catch (AttributeReadOnlyException e) {
0292:                    throw new WMWorkflowException(e);
0293:                }
0294:            }
0295:
0296:            /**
0297:             * Calculates the expiration date for an application event.
0298:             *
0299:             * @param expiration      The duration for which the event will be valid.
0300:             * @param calendar        The name of the business calendar to use.
0301:             * @param calendarFactory The calendar factory to use.
0302:             * @return The expiration date.
0303:             * @throws RepositoryException If the calendar could not be found.
0304:             */
0305:            public static Date calculateExpiryDate(Duration expiration,
0306:                    String calendar, CalendarFactory calendarFactory)
0307:                    throws RepositoryException {
0308:
0309:                return calendarFactory.findCalendar(calendar).add(new Date(),
0310:                        expiration.getUnit(), expiration.getValue(), null);
0311:            }
0312:
0313:            /**
0314:             * Calculates the deadline date for an activity.
0315:             *
0316:             * @param activity
0317:             * @param deadline
0318:             * @param startedDate
0319:             * @param calendarFactory
0320:             * @return
0321:             * @throws RepositoryException
0322:             */
0323:            public static Date calculateDeadlineDate(Activity activity,
0324:                    Deadline deadline, Date startedDate,
0325:                    CalendarFactory calendarFactory) throws RepositoryException {
0326:
0327:                try {
0328:                    return dateAdd(activity, null, null, startedDate, deadline
0329:                            .getDuration(), calendarFactory);
0330:                } catch (WMInvalidTargetUserException e) {
0331:                    // Can't happen since we're not passing a performer.
0332:                    throw new RepositoryException(e);
0333:                }
0334:            }
0335:
0336:            /**
0337:             * Calculates the due date for a workflow.
0338:             *
0339:             * @param workflow
0340:             * @param startedDate
0341:             * @param calendarFactory
0342:             * @return The due date, or null if the workflow does not specify a limit.
0343:             */
0344:            public static Date calculateDueDate(WorkflowProcess workflow,
0345:                    Date startedDate, CalendarFactory calendarFactory)
0346:                    throws RepositoryException {
0347:
0348:                return dateAdd(workflow, startedDate, workflow
0349:                        .getProcessHeader().getLimit(), calendarFactory);
0350:            }
0351:
0352:            /**
0353:             * Calculates the due date for an activity.
0354:             *
0355:             * @param activity
0356:             * @param performer
0357:             * @param user
0358:             * @param startedDate
0359:             * @param calendarFactory
0360:             * @return The due date, or null if the activity does not specify a limit.
0361:             */
0362:            public static Date calculateDueDate(Activity activity,
0363:                    String performer, String user, Date startedDate,
0364:                    CalendarFactory calendarFactory)
0365:                    throws RepositoryException, WMInvalidTargetUserException {
0366:
0367:                return dateAdd(activity, performer, user, startedDate, activity
0368:                        .getLimit(), calendarFactory);
0369:            }
0370:
0371:            /**
0372:             * Calculates the target date for a workflow.
0373:             *
0374:             * @param workflow
0375:             * @param startedDate
0376:             * @param calendarFactory
0377:             * @return The target date, or null if the workflow does not specify a
0378:             *         duration.
0379:             */
0380:            public static Date calculateTargetDate(WorkflowProcess workflow,
0381:                    Date startedDate, CalendarFactory calendarFactory)
0382:                    throws RepositoryException {
0383:
0384:                TimeEstimation te = workflow.getProcessHeader()
0385:                        .getTimeEstimation();
0386:                Duration duration = te == null ? null : te.getDuration();
0387:                return dateAdd(workflow, startedDate, duration, calendarFactory);
0388:            }
0389:
0390:            /**
0391:             * Calculates the target date for an activity.
0392:             *
0393:             * @param activity
0394:             * @param performer
0395:             * @param user
0396:             * @param startedDate
0397:             * @param calendarFactory
0398:             * @return The due date, or null if the activity does not specify a limit.
0399:             */
0400:            public static Date calculateTargetDate(Activity activity,
0401:                    String performer, String user, Date startedDate,
0402:                    CalendarFactory calendarFactory)
0403:                    throws RepositoryException, WMInvalidTargetUserException {
0404:
0405:                Duration duration = null;
0406:                SimulationInformation si = activity.getSimulationInformation();
0407:                if (si != null) {
0408:                    TimeEstimation te = si.getTimeEstimation();
0409:                    if (te != null)
0410:                        duration = te.getDuration();
0411:                }
0412:                return dateAdd(activity, performer, user, startedDate,
0413:                        duration, calendarFactory);
0414:            }
0415:
0416:            /**
0417:             * Synthesizes a conditional expression from a set of formal and actual
0418:             * parameter specifications.  The key/value pairs for all parameters are
0419:             * ANDed together in the resulting conditional expression.
0420:             *
0421:             * @param metaData    The event definition contains the formal parameters which
0422:             *                    define the keys referenced in the resulting conditional expression.
0423:             * @param actualParms The actual parameters define the values to match
0424:             *                    against their corresponding keys.
0425:             * @param ctx         The workflow context in which to evaluate the actual
0426:             *                    parameters.
0427:             * @return A conditional expression in the specified scripting language.
0428:             * @throws WMWorkflowException
0429:             */
0430:            public static String createEventCondition(
0431:                    EventTypeMetaData metaData, ActualParameter[] actualParms,
0432:                    EngineContext ctx) throws WMWorkflowException {
0433:
0434:                StringBuffer sb = new StringBuffer();
0435:                try {
0436:                    // Find the event definition.
0437:                    ServiceManager svcMgr = ctx.getServiceManager();
0438:
0439:                    // TODO: support other scripting languages in addition to XPath.
0440:                    String scriptType = metaData.getScriptType();
0441:                    if (!scriptType.equals(MIMETypes.XPATH)) {
0442:                        throw new IllegalArgumentException(
0443:                                "Unsupported condition scripting language: "
0444:                                        + scriptType);
0445:                    }
0446:
0447:                    WorkflowProcess workflow = ctx.getWorkflow();
0448:                    ProcessInstance processInstance = ctx.getProcessInstance();
0449:                    Map attrs = processInstance == null ? null
0450:                            : processInstance.getAttributeInstances();
0451:                    Evaluator evaluator = null;
0452:
0453:                    // Iterate through the parameters and build the expression.
0454:                    EventParameter[] formalParms = metaData
0455:                            .getFormalParameter();
0456:                    for (int i = 0, n = formalParms.length; i < n; i++) {
0457:                        EventParameter fp = formalParms[i];
0458:                        ActualParameter ap = actualParms[i];
0459:                        String text = ap.getText();
0460:                        Object value = null;
0461:                        ParameterMode mode = fp.getMode();
0462:                        if (mode == null)
0463:                            mode = ParameterMode.IN;
0464:                        switch (mode.value()) {
0465:                        case ParameterMode.IN_INT:
0466:                            // IN parameter: text is an expression to evaluate.
0467:                            if (text != null && text.length() > 0) {
0468:                                if (evaluator == null) {
0469:                                    evaluator = getEvaluator(workflow
0470:                                            .getPackage(), svcMgr);
0471:                                }
0472:                                value = evaluator.evaluateExpression(text, ctx);
0473:                            }
0474:                            break;
0475:                        case ParameterMode.INOUT_INT:
0476:                            // INOUT parameter: text is the name of the attr to pass.
0477:                            if (attrs != null) {
0478:                                AttributeInstance attributeInstance = (AttributeInstance) attrs
0479:                                        .get(text);
0480:                                if (attributeInstance == null)
0481:                                    throw new WMInvalidAttributeException(text);
0482:                                value = attributeInstance.getValue();
0483:                            }
0484:                            break;
0485:                        case ParameterMode.OUT_INT:
0486:                            return sb.toString();
0487:                        }
0488:                        // Test the key value expression for equality with the supplied
0489:                        // actual parameter value.
0490:                        sb.append(fp.getKeyExpression());
0491:                        sb.append(" = ");
0492:                        Type dataType = fp.getDataType().getType();
0493:                        if (dataType.equals(BasicType.STRING)) {
0494:                            sb.append('\'');
0495:                            sb.append(value);
0496:                            sb.append('\'');
0497:                        } else if (dataType.equals(BasicType.BOOLEAN)) {
0498:                            sb.append(value);
0499:                            sb.append("()");
0500:                        } else {
0501:                            sb.append(value);
0502:                        }
0503:                        if (i < n - 1)
0504:                            sb.append(" and ");
0505:                    }
0506:                } catch (EvaluatorException e) {
0507:                    throw new WMWorkflowException(e);
0508:                } catch (RepositoryException e) {
0509:                    throw new WMWorkflowException(e);
0510:                }
0511:                return sb.toString();
0512:            }
0513:
0514:            /**
0515:             * Creates the keys for a key-based event subscription.
0516:             *
0517:             * @param metaData    Event type meta data.
0518:             * @param actualParms The actual parameters from the
0519:             *                    <code>&lt;obe:Event&gt;</code> element in the workflow process.
0520:             * @param ctx         The engine context.
0521:             * @return Event keys for the IN- and INOUT-type formal event parameters.
0522:             * @throws WMWorkflowException
0523:             */
0524:            public static Object[] createEventKeys(EventTypeMetaData metaData,
0525:                    ActualParameter[] actualParms, EngineContext ctx)
0526:                    throws WMWorkflowException {
0527:
0528:                EventParameter[] formalParms = metaData.getFormalParameter();
0529:                List eventKeys = new ArrayList(actualParms.length);
0530:                try {
0531:                    ServiceManager svcMgr = ctx.getServiceManager();
0532:                    DataConverter dataConverter = svcMgr.getDataConverter();
0533:                    WorkflowProcess workflow = ctx.getWorkflow();
0534:                    ProcessInstance processInstance = ctx.getProcessInstance();
0535:                    Map attrs = processInstance == null ? null
0536:                            : processInstance.getAttributeInstances();
0537:                    Evaluator evaluator = null;
0538:                    for (int i = 0, m = formalParms.length, n = actualParms.length; i < n; i++) {
0539:
0540:                        // varargs pattern: reuse the last formal parameter as necessary.
0541:                        FormalParameter formalParm = formalParms[i < m ? i
0542:                                : m - 1];
0543:                        ActualParameter actualParm = actualParms[i];
0544:                        String text = actualParm.getText();
0545:                        Object value = null;
0546:                        ParameterMode mode = formalParm.getMode();
0547:                        if (mode == null)
0548:                            mode = ParameterMode.IN;
0549:                        switch (mode.value()) {
0550:                        case ParameterMode.IN_INT:
0551:                            // IN parameter: text is an expression to evaluate.
0552:                            if (text != null && text.length() > 0) {
0553:                                if (evaluator == null) {
0554:                                    evaluator = getEvaluator(workflow
0555:                                            .getPackage(), svcMgr);
0556:                                }
0557:                                value = evaluator.evaluateExpression(text, ctx);
0558:                            } else {
0559:                                value = null;
0560:                            }
0561:                            break;
0562:                        case ParameterMode.INOUT_INT:
0563:                            // INOUT parameter: text is the name of the attr to pass.
0564:                            if (attrs != null) {
0565:                                AttributeInstance attributeInstance = (AttributeInstance) attrs
0566:                                        .get(text);
0567:                                if (attributeInstance == null)
0568:                                    throw new WMInvalidAttributeException(text);
0569:                                value = attributeInstance.getValue();
0570:                            }
0571:                            break;
0572:                        case ParameterMode.OUT_INT:
0573:                            // Event parameters must declare OUT parameters last.
0574:                            return eventKeys.toArray();
0575:                        }
0576:
0577:                        // Ensure that the parameter value is of the required class.
0578:                        // N.B. If the FormalParameters came from an external reference
0579:                        // (e.g., defined in a repository), data types may not be
0580:                        // specified, in which case just use the actual data type.
0581:                        DataType formalDataType = formalParm.getDataType();
0582:                        if (formalDataType != null) {
0583:                            value = dataConverter.convertValue(value, DataTypes
0584:                                    .classForDataType(formalDataType));
0585:                        }
0586:
0587:                        eventKeys.add(value);
0588:                    }
0589:                } catch (EvaluatorException e) {
0590:                    throw new WMWorkflowException(e);
0591:                } catch (RepositoryException e) {
0592:                    throw new WMWorkflowException(e);
0593:                }
0594:                return eventKeys.toArray();
0595:            }
0596:
0597:            public static Parameter[] createParameters(
0598:                    FormalParameter[] formalParms,
0599:                    ActualParameter[] actualParms, EngineContext ctx)
0600:                    throws WMWorkflowException {
0601:
0602:                Parameter[] parms = new Parameter[actualParms.length];
0603:                try {
0604:                    ServiceManager svcMgr = ctx.getServiceManager();
0605:                    DataConverter dataConverter = svcMgr.getDataConverter();
0606:                    WorkflowProcess workflow = ctx.getWorkflow();
0607:                    ProcessInstance processInstance = ctx.getProcessInstance();
0608:                    Map attrs = processInstance.getAttributeInstances();
0609:                    Evaluator evaluator = null;
0610:                    for (int i = 0, m = formalParms.length, n = actualParms.length; i < n; i++) {
0611:
0612:                        // varargs pattern: reuse the last formal parameter as necessary.
0613:                        FormalParameter formalParm = formalParms[i < m ? i
0614:                                : m - 1];
0615:                        ActualParameter actualParm = actualParms[i];
0616:                        AttributeDescription attrDesc;
0617:                        String id;
0618:                        String name;
0619:                        String description;
0620:                        DataType dataType;
0621:                        String text = actualParm.getText();
0622:                        Object value;
0623:                        ParameterMode mode = formalParm.getMode();
0624:                        if (mode == null)
0625:                            mode = ParameterMode.IN;
0626:                        switch (mode.value()) {
0627:                        case ParameterMode.IN_INT:
0628:                            // IN parameter: text is an expression to evaluate.
0629:                            id = null;
0630:                            name = null;
0631:                            description = null;
0632:                            dataType = null;
0633:                            if (text != null && text.length() > 0) {
0634:                                if (evaluator == null) {
0635:                                    evaluator = getEvaluator(workflow
0636:                                            .getPackage(), svcMgr);
0637:                                }
0638:                                value = evaluator.evaluateExpression(text, ctx);
0639:                            } else {
0640:                                value = null;
0641:                            }
0642:                            break;
0643:                        case ParameterMode.INOUT_INT:
0644:                            id = text;
0645:                            attrDesc = describeAttribute(workflow, id, true);
0646:                            name = attrDesc.name;
0647:                            description = attrDesc.description;
0648:                            dataType = attrDesc.dataType;
0649:                            // INOUT parameter: text is the name of the attr to pass.
0650:                            value = ((AttributeInstance) attrs.get(text))
0651:                                    .getValue();
0652:                            break;
0653:                        case ParameterMode.OUT_INT:
0654:                            id = text;
0655:                            attrDesc = describeAttribute(workflow, id, true);
0656:                            name = attrDesc.name;
0657:                            description = attrDesc.description;
0658:                            dataType = attrDesc.dataType;
0659:                            // OUT parameter: no value to pass.
0660:                            value = null;
0661:                            break;
0662:                        default:
0663:                            continue; // (Can't actually happen)
0664:                        }
0665:
0666:                        // Ensure that the parameter value is of the required class.
0667:                        // N.B. If the FormalParameters came from an external reference
0668:                        // (e.g., defined in a repository), data types may not be
0669:                        // specified, in which case just use the actual data type.
0670:                        DataType formalDataType = formalParm.getDataType();
0671:                        Class formalClass = null;
0672:                        if (formalDataType != null) {
0673:                            formalClass = DataTypes
0674:                                    .classForDataType(formalDataType);
0675:                            value = dataConverter.convertValue(value,
0676:                                    formalClass);
0677:                        }
0678:
0679:                        parms[i] = new Parameter(formalParm, formalClass, id,
0680:                                name, description, dataType, mode, value);
0681:                    }
0682:                } catch (EvaluatorException e) {
0683:                    throw new WMWorkflowException(e);
0684:                } catch (RepositoryException e) {
0685:                    throw new WMWorkflowException(e);
0686:                }
0687:                return parms;
0688:            }
0689:
0690:            public static Parameter[] createParameters(Application toolDef,
0691:                    ActualParameter[] actualParms, EngineContext ctx)
0692:                    throws WMWorkflowException {
0693:
0694:                FormalParameter[] formalParms;
0695:
0696:                ExternalReference extRef = toolDef.getExternalReference();
0697:                if (extRef == null) {
0698:                    formalParms = toolDef.getFormalParameter();
0699:                } else {
0700:                    // If the tool is described by an external reference which we haven't
0701:                    // yet analysed, introspect the external reference to determine the
0702:                    // formal parameter types.
0703:                    try {
0704:                        ToolAgentMetaData metaData = ctx.getServiceManager()
0705:                                .getToolAgentFactory()
0706:                                .findToolMetaData(toolDef);
0707:                        formalParms = metaData.getFormalParameter();
0708:                    } catch (ObjectNotFoundException e) {
0709:                        throw new WMInvalidToolException(extRef.toString());
0710:                    } catch (RepositoryException e) {
0711:                        throw new WMWorkflowException(e);
0712:                    }
0713:                }
0714:
0715:                return createParameters(formalParms, actualParms, ctx);
0716:            }
0717:
0718:            private static Date dateAdd(WorkflowProcess workflow, Date date,
0719:                    Duration duration, CalendarFactory calendarFactory)
0720:                    throws RepositoryException {
0721:
0722:                Date result = null;
0723:                if (duration != null) {
0724:                    int amount = duration.getValue();
0725:                    if (amount != 0) {
0726:                        DurationUnit unit = duration.getUnit();
0727:                        if (unit == null) {
0728:                            unit = workflow.getProcessHeader()
0729:                                    .getDurationUnit();
0730:                            if (unit == null)
0731:                                unit = DurationUnit.DEFAULT;
0732:                        }
0733:                        String calendar = findCalendar(workflow);
0734:                        result = calendarFactory.findCalendar(calendar).add(
0735:                                date, unit, amount, null);
0736:                    }
0737:                }
0738:                return result;
0739:            }
0740:
0741:            private static Date dateAdd(Activity activity, String performer,
0742:                    String user, Date date, Duration duration,
0743:                    CalendarFactory calendarFactory)
0744:                    throws RepositoryException, WMInvalidTargetUserException {
0745:
0746:                Date result = null;
0747:                if (duration != null) {
0748:                    int amount = duration.getValue();
0749:                    if (amount != 0) {
0750:                        DurationUnit unit = duration.getUnit();
0751:                        if (unit == null) {
0752:                            unit = activity.getWorkflowProcess()
0753:                                    .getProcessHeader().getDurationUnit();
0754:                            if (unit == null)
0755:                                unit = DurationUnit.DEFAULT;
0756:                        }
0757:                        String calendar = findCalendar(performer, activity);
0758:                        result = calendarFactory.findCalendar(calendar).add(
0759:                                date, unit, amount, user);
0760:                    }
0761:                }
0762:                return result;
0763:            }
0764:
0765:            public static AssignmentStrategyDef findAssignmentStrategy(
0766:                    Activity activity) {
0767:
0768:                AssignmentStrategyDef strategy = activity
0769:                        .getAssignmentStrategy();
0770:                if (strategy == null) {
0771:                    WorkflowProcess workflow = activity.getWorkflowProcess();
0772:                    strategy = workflow.getAssignmentStrategy();
0773:                    if (strategy == null) {
0774:                        strategy = workflow.getPackage()
0775:                                .getAssignmentStrategy();
0776:                        if (strategy == null)
0777:                            strategy = AssignmentStrategyDef.DEFAULT;
0778:                    }
0779:                }
0780:                return strategy;
0781:            }
0782:
0783:            /**
0784:             * Finds the name of the business calendar to use.
0785:             *
0786:             * @param workflow Workflow definition to search.
0787:             * @return The business calendar name, or <code>&quot;default&quot;</code>
0788:             *         if a calendar was not specified by the WorkflowProcess or Package.
0789:             */
0790:            public static String findCalendar(WorkflowProcess workflow) {
0791:                String calendar = workflow.getCalendar();
0792:                if (calendar == null) {
0793:                    calendar = workflow.getPackage().getCalendar();
0794:                    if (calendar == null)
0795:                        calendar = "default";
0796:                }
0797:                return calendar;
0798:            }
0799:
0800:            /**
0801:             * Finds the name of the business calendar to use.
0802:             *
0803:             * @param performer The ID of the performer for whom the computation is
0804:             *                  being made.  The corresponding participant can have its own calendar,
0805:             *                  which will over-ride any activity-, workflow- or package-level calendar.
0806:             * @param activity  The activity definition to search.
0807:             * @return The business calendar ID, or <code>&quot;default&quot;</code> if
0808:             *         a calendar was not specified by the Activity, WorkflowProcess or Package.
0809:             */
0810:            public static String findCalendar(String performer,
0811:                    Activity activity) throws WMInvalidTargetUserException {
0812:
0813:                String calendar = null;
0814:
0815:                WorkflowProcess workflow = activity.getWorkflowProcess();
0816:                if (performer != null) {
0817:                    Participant participant = WorkflowUtilities
0818:                            .findParticipant(workflow, performer);
0819:                    calendar = participant.getCalendar();
0820:                }
0821:                if (calendar == null) {
0822:                    calendar = activity.getCalendar();
0823:                    if (calendar == null)
0824:                        calendar = findCalendar(workflow);
0825:                }
0826:
0827:                return calendar;
0828:            }
0829:
0830:            public static CompletionStrategy findCompletionStrategy(
0831:                    Activity activity, ServiceManager svcMgr)
0832:                    throws WMWorkflowException {
0833:
0834:                try {
0835:                    String strategy = activity.getCompletionStrategy();
0836:                    if (strategy == null) {
0837:                        WorkflowProcess workflow = activity
0838:                                .getWorkflowProcess();
0839:                        strategy = workflow.getCompletionStrategy();
0840:                        if (strategy == null) {
0841:                            strategy = workflow.getPackage()
0842:                                    .getCompletionStrategy();
0843:                            if (strategy == null)
0844:                                strategy = "ALL";
0845:                        }
0846:                    }
0847:                    return svcMgr.getCompletionStrategyFactory().findStrategy(
0848:                            strategy);
0849:                } catch (RepositoryException e) {
0850:                    throw new WMWorkflowException(e);
0851:                }
0852:            }
0853:
0854:            /**
0855:             * Finds the definition of a process attribute.
0856:             *
0857:             * @param id The attribute ID.
0858:             * @return The attribute definition.
0859:             * @throws ObjectNotFoundException if the attribute could not be found.
0860:             */
0861:            public static DataField findDataField(WorkflowProcess workflow,
0862:                    String id) throws ObjectNotFoundException {
0863:
0864:                DataField field = ProcessInstanceAttributes
0865:                        .findSystemDataField(id);
0866:                if (field != null)
0867:                    return field;
0868:                DataField[] dataFields = workflow.getDataField();
0869:                for (int j = 0, n = dataFields.length; j < n; j++) {
0870:                    field = dataFields[j];
0871:                    if (field.getId().equals(id))
0872:                        return field;
0873:                }
0874:                dataFields = workflow.getPackage().getDataField();
0875:                for (int j = 0, n = dataFields.length; j < n; j++) {
0876:                    field = dataFields[j];
0877:                    if (field.getId().equals(id))
0878:                        return field;
0879:                }
0880:                throw new ObjectNotFoundException(id);
0881:            }
0882:
0883:            /**
0884:             * Describes a process attribute.
0885:             *
0886:             * @param workflow           The workflow definition.
0887:             * @param id                 The attribute ID.
0888:             * @param includeSystemAttrs <code>true</code> to include system attributes.
0889:             * @return The corresponding DataType.
0890:             */
0891:            public static DataType findDataType(WorkflowProcess workflow,
0892:                    String id, boolean includeSystemAttrs)
0893:                    throws WMInvalidAttributeException {
0894:
0895:                return describeAttribute(workflow, id, includeSystemAttrs).dataType;
0896:            }
0897:
0898:            /**
0899:             * Describes a process attribute.
0900:             *
0901:             * @param workflow           The workflow definition.
0902:             * @param id                 The attribute ID.
0903:             * @param includeSystemAttrs <code>true</code> to include system attributes.
0904:             * @return A description of the attribute.
0905:             */
0906:            public static AttributeDescription describeAttribute(
0907:                    WorkflowProcess workflow, String id,
0908:                    boolean includeSystemAttrs)
0909:                    throws WMInvalidAttributeException {
0910:
0911:                String name = null;
0912:                String description = null;
0913:                DataField dataField = includeSystemAttrs ? ProcessInstanceAttributes
0914:                        .findSystemDataField(id)
0915:                        : null;
0916:                if (dataField == null) {
0917:                    dataField = workflow.getDataField(id);
0918:                    if (dataField == null)
0919:                        dataField = workflow.getPackage().getDataField(id);
0920:                }
0921:                DataType dataType = null;
0922:                if (dataField != null) {
0923:                    dataType = dataField.getDataType();
0924:                    name = dataField.getName();
0925:                    description = dataField.getDescription();
0926:                } else {
0927:                    FormalParameter fp = workflow.getFormalParameter(id);
0928:                    if (fp != null) {
0929:                        dataType = fp.getDataType();
0930:                        name = id;
0931:                        description = fp.getDescription();
0932:                    }
0933:                }
0934:                if (dataType == null)
0935:                    throw new WMInvalidAttributeException(id);
0936:                if (name == null)
0937:                    name = id;
0938:
0939:                return new AttributeDescription(id, name, description, dataType);
0940:            }
0941:
0942:            public static Evaluator getEvaluator(XPDLPackage pkg,
0943:                    ServiceManager svcMgr) throws RepositoryException {
0944:
0945:                // Determine script type; default is text/x-xpath.
0946:                Script script = pkg.getScript();
0947:                String contentType = script == null ? ServerConfig
0948:                        .getScriptType() : script.getType();
0949:                return svcMgr.getEvaluatorFactory().findEvaluator(contentType);
0950:            }
0951:
0952:            /**
0953:             * Introspects properties of the specified class(es) into a map.  The
0954:             * results are cached internally on <code>beanClass<code>, with the result
0955:             * that sequential calls with the same <code>beanClass<code> but different
0956:             * <code>stopClass<code> will yield property information generated from the
0957:             * first such call.
0958:             *
0959:             * @param beanClass
0960:             * @param stopClass
0961:             * @return A map of <code>PropertyDescriptor</code>s, keyed on property
0962:             *         name.
0963:             */
0964:            public static Map introspectToMap(Class beanClass, Class stopClass) {
0965:                Map map = (Map) _propDescs.get(beanClass);
0966:                if (map == null) {
0967:                    map = new HashMap();
0968:                    PropertyDescriptor[] propDescs = ClassUtils.introspect(
0969:                            beanClass, stopClass);
0970:                    for (int i = 0; i < propDescs.length; i++) {
0971:                        PropertyDescriptor propDesc = propDescs[i];
0972:                        map.put(propDesc.getName(), propDesc);
0973:                    }
0974:                    _propDescs.put(beanClass, map);
0975:                }
0976:                return map;
0977:            }
0978:
0979:            public static String mapPerformerId(Participant performerDef)
0980:                    throws WMInvalidTargetUserException {
0981:
0982:                String performerId = performerDef.getId();
0983:
0984:                // An external reference can map Role:Group or Human:Principal.
0985:                ExternalReference extRef = performerDef.getExternalReference();
0986:                if (extRef != null) {
0987:                    // If the external reference location is the OBE realm, the
0988:                    // mapping is given by the xref.
0989:                    if (SecurityRealm.XPDL_NAME.equals(extRef.getLocation())) {
0990:                        String xref = extRef.getXref();
0991:                        if (xref == null || xref.length() == 0)
0992:                            throw new WMInvalidTargetUserException(performerId);
0993:
0994:                        if (_logger.isDebugEnabled()) {
0995:                            _logger.debug("resolved participant '"
0996:                                    + performerId + "' to external reference: "
0997:                                    + xref);
0998:                        }
0999:                        performerId = xref;
1000:                    } else {
1001:                        _logger.info("Unknown external reference " + extRef
1002:                                + " ignored");
1003:                    }
1004:                }
1005:                return performerId;
1006:            }
1007:
1008:            /**
1009:             * Returns everything necessary to invoke the tool(s) associated with a work
1010:             * item.
1011:             *
1012:             * @param workItem  The work item corresponding to the tool.
1013:             * @param toolIndex The index of the tool to prepare (ignored in favour of
1014:             *                  <code>workItem.getToolIndex()</code> if <code>workItem</code> is
1015:             *                  non-null or if the toolset mode is PARALLEL.
1016:             * @param ctx       The workflow context in which to prepare the tool invocation.
1017:             * @return Tool invocation details.
1018:             * @throws WMInvalidToolException if the tool cannot be found.
1019:             */
1020:            public static ToolInvocation[] prepareToolInvocations(
1021:                    WorkItem workItem, int toolIndex, EngineContext ctx)
1022:                    throws RepositoryException, WMWorkflowException {
1023:
1024:                ToolInvocation[] ti;
1025:                Activity activity = ctx.getActivity();
1026:                Implementation implementation = activity.getImplementation();
1027:                if (implementation instanceof  ToolSet) {
1028:                    // If the tool execution mode is PARALLEL, prepare all tool
1029:                    // invocations.  Otherwise, just prepare the tool invocation for the
1030:                    // work item's current tool index.
1031:                    boolean parallel = activity.getToolMode() == ToolMode.PARALLEL;
1032:                    boolean serverSide = workItem == null;
1033:                    ToolSet toolSet = (ToolSet) implementation;
1034:                    Tool[] tools = toolSet.getTool();
1035:                    List invocations = new ArrayList(parallel ? tools.length
1036:                            : 1);
1037:
1038:                    ToolAgentFactory factory = ctx.getServiceManager()
1039:                            .getToolAgentFactory();
1040:                    WorkflowProcess workflow = ctx.getWorkflow();
1041:                    ActivityInstance activityInstance = ctx
1042:                            .getActivityInstance();
1043:                    String processInstanceId;
1044:                    String workItemId;
1045:                    if (workItem != null) {
1046:                        processInstanceId = workItem.getProcessInstanceId();
1047:                        workItemId = workItem.getWorkItemId();
1048:                        toolIndex = workItem.getToolIndex();
1049:                    } else {
1050:                        processInstanceId = ctx.getProcessInstance()
1051:                                .getProcessInstanceId();
1052:                        workItemId = null;
1053:                    }
1054:                    ctx.setWorkItem(workItem);
1055:
1056:                    // Prepare an invocation for each of the tools to be executed.
1057:                    for (int i = parallel ? 0 : toolIndex, n = tools.length; i < n; i++) {
1058:                        // Build the parameter list.
1059:                        Tool tool = tools[i];
1060:
1061:                        // The server only ever invokes PROCEDURES.
1062:                        if (serverSide
1063:                                && tool.getToolType() == ToolType.APPLICATION) {
1064:                            _logger.warn("Ignoring APPLICATION-type tool '"
1065:                                    + tool.getId() + "' in activity '"
1066:                                    + activity + "' of workflow '" + workflow
1067:                                    + '\'');
1068:                            continue;
1069:                        }
1070:
1071:                        // Evaluate the tool invocation parameters.
1072:                        String toolId = tool.getId();
1073:                        Application toolDef = WorkflowUtilities
1074:                                .findToolDefinition(workflow, toolId);
1075:                        ctx.setTool(tool);
1076:                        Parameter[] parms = createParameters(toolDef, tool
1077:                                .getActualParameter(), ctx);
1078:                        ctx.setTool(null);
1079:
1080:                        // Find the tool meta-data and the tool agent.
1081:                        ToolAgentMetaData metaData = factory
1082:                                .findToolMetaData(toolDef);
1083:                        ToolAgent agent = factory.findToolAgent(toolDef, parms);
1084:
1085:                        // Create the tool invocation.
1086:                        invocations.add(new ToolInvocation(processInstanceId,
1087:                                activityInstance.getName(), workItemId, toolId,
1088:                                i, metaData, tool.getToolType(), agent, parms,
1089:                                activity.getDescription()));
1090:
1091:                        // Work items invoke sequentially executed tools one at a time.
1092:                        if (!parallel)
1093:                            break;
1094:                    }
1095:
1096:                    ti = (ToolInvocation[]) invocations
1097:                            .toArray(new ToolInvocation[invocations.size()]);
1098:                } else if (implementation instanceof  NoImplementation) {
1099:                    ti = new ToolInvocation[] { new ToolInvocation(workItem
1100:                            .getProcessInstanceId(), workItem.getName(),
1101:                            workItem.getWorkItemId(), null, 0,
1102:                            NoImplementationToolAgent.META_DATA, null,
1103:                            NoImplementationToolAgent.INSTANCE, null, activity
1104:                                    .getDescription()) };
1105:                } else {
1106:                    ti = EMPTY_TOOL_INVOCATIONS;
1107:                }
1108:
1109:                return ti;
1110:            }
1111:
1112:            /**
1113:             * Maps process state to activity state.  When a process instance
1114:             * transitions to the <code>newState</code> state, activities belonging
1115:             * to that process instance and for which it would be a legal transition,
1116:             * should transition to the state returned by this method.
1117:             *
1118:             * @param newState The new process instance state.
1119:             * @return The required activity instance state.
1120:             */
1121:            public static int processStateToActivityState(int newState) {
1122:                // The states actually have the same ordinals.
1123:                return newState;
1124:            }
1125:
1126:            /**
1127:             * Validates that a WorkflowProcess is available for instantiation.
1128:             *
1129:             * @param workflow The WorkflowProcess
1130:             * @param internal <code>true</code> if instantiating internally.
1131:             * @throws WMInvalidProcessDefinitionException
1132:             *          if the process definition is
1133:             *          disabled, under revision, private and non-subflow, or has not yet come
1134:             *          into force, or has expired.
1135:             */
1136:            public static void checkValid(WorkflowProcess workflow,
1137:                    boolean internal)
1138:                    throws WMInvalidProcessDefinitionException {
1139:
1140:                RedefinableHeader rhdr = workflow.getRedefinableHeader();
1141:                if (rhdr == null)
1142:                    rhdr = workflow.getPackage().getRedefinableHeader();
1143:                String procDefId = workflow.getId();
1144:
1145:                // Cannot instantiate if disabled.
1146:                if (workflow.getState() != WMProcessDefinitionState.ENABLED_INT) {
1147:                    throw new WMInvalidProcessDefinitionException("Workflow "
1148:                            + procDefId
1149:                            + " is disabled and cannot be instantiated.");
1150:                }
1151:
1152:                // Cannot instantiate if UNDER_REVISISION.
1153:                PublicationStatus status = rhdr == null ? null : rhdr
1154:                        .getPublicationStatus();
1155:                if (status == PublicationStatus.UNDER_REVISION) {
1156:                    throw new WMInvalidProcessDefinitionException("Workflow "
1157:                            + procDefId
1158:                            + " is under revision and cannot be instantiated.");
1159:                }
1160:
1161:                // Private workflows can only be instantiated as subflows.
1162:                if (!internal
1163:                        && workflow.getAccessLevel() == AccessLevel.PRIVATE) {
1164:                    throw new WMInvalidProcessDefinitionException("Workflow "
1165:                            + procDefId
1166:                            + " is private and cannot be instantiated.");
1167:                }
1168:
1169:                ProcessHeader procHdr = workflow.getProcessHeader();
1170:                long now = System.currentTimeMillis();
1171:
1172:                // Cannot instantiate if it isn't yet valid.
1173:                Date validFrom = procHdr.getValidFrom();
1174:                if (validFrom != null && now < validFrom.getTime()) {
1175:                    throw new WMInvalidProcessDefinitionException("Workflow "
1176:                            + procDefId
1177:                            + " is not yet valid and cannot be instantiated.");
1178:                }
1179:
1180:                // Cannot instantiate if it's expired.
1181:                Date validTo = procHdr.getValidTo();
1182:                if (validTo != null && now > validTo.getTime()) {
1183:                    throw new WMInvalidProcessDefinitionException("Workflow "
1184:                            + procDefId
1185:                            + " has expired and cannot be instantiated.");
1186:                }
1187:            }
1188:
1189:            /**
1190:             * Sorts the workflows collection in ordered of descending validity,
1191:             * namely: validFrom DESC, validTo DESC, created DESC.  The 'most valid'
1192:             * workflow is therefore always at index 0.
1193:             *
1194:             * @param workflows
1195:             */
1196:            public static void sortForValidity(WorkflowProcess[] workflows) {
1197:                Arrays.sort(workflows, _workflowValidityComparator);
1198:            }
1199:
1200:            private WorkflowEngineUtilities() {
1201:            }
1202:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.