Source Code Cross Referenced for PackageValidator.java in  » Workflow-Engines » obe-1.0 » org » obe » client » api » xpdl » 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.client.api.xpdl 
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.client.api.xpdl;
0046:
0047:        import org.apache.commons.logging.Log;
0048:        import org.apache.commons.logging.LogFactory;
0049:        import org.obe.xpdl.XPDLNames;
0050:        import org.obe.xpdl.model.activity.*;
0051:        import org.obe.xpdl.model.application.Application;
0052:        import org.obe.xpdl.model.condition.Condition;
0053:        import org.obe.xpdl.model.condition.ConditionType;
0054:        import org.obe.xpdl.model.data.*;
0055:        import org.obe.xpdl.model.ext.Event;
0056:        import org.obe.xpdl.model.misc.*;
0057:        import org.obe.xpdl.model.participant.Participant;
0058:        import org.obe.xpdl.model.pkg.ExternalPackage;
0059:        import org.obe.xpdl.model.pkg.PackageHeader;
0060:        import org.obe.xpdl.model.pkg.XPDLPackage;
0061:        import org.obe.xpdl.model.transition.*;
0062:        import org.obe.xpdl.model.workflow.ProcessHeader;
0063:        import org.obe.xpdl.model.workflow.WorkflowProcess;
0064:        import org.obe.xpdl.parser.dom4j.Dom4JXPDLParser;
0065:        import org.obe.xpdl.parser.XPDLParser;
0066:        import org.obe.client.api.model.ProcessInstanceAttributes;
0067:
0068:        import java.io.FileInputStream;
0069:        import java.io.FileReader;
0070:        import java.io.InputStream;
0071:        import java.io.Reader;
0072:        import java.util.*;
0073:
0074:        // TODO: use standard XPath expressions for the prefix.
0075:
0076:        /**
0077:         * Validates an XPDL package bean.
0078:         *
0079:         * @author Adrian Price
0080:         */
0081:        public final class PackageValidator implements  PackageValidatorMessages {
0082:            private static final Log _logger = LogFactory
0083:                    .getLog(PackageValidator.class);
0084:            public static final String GRAPH_CONFORMANCE_MIN_PROP = "graph.conformance.minimum";
0085:            private static final String PKG_APPLICATION = "Application(Package)";
0086:            private static final String PKG_DATA_FIELD = "DataField(Package)";
0087:            private static final String PKG_PARTICIPANT = "Participant(Package)";
0088:            private static final String WORKFLOW_FORMAL_PARAMETER = "FormalParameter(Workflow)";
0089:            public static final String OTHERWISE_TRANSITION_ALREADY_DEFINED = " an OTHERWISE transition has already been defined";
0090:            private static final String[][] DEFAULTS = { {
0091:                    GRAPH_CONFORMANCE_MIN_PROP,
0092:                    GraphConformance.NON_BLOCKED.toString() }, };
0093:            private static final Set _countryCodes = new TreeSet();
0094:            private static final Properties _defaultProps = new Properties();
0095:            private Properties _props = new Properties(_defaultProps);
0096:
0097:            static {
0098:                // Extract valid country codes from the available locales.
0099:                Locale[] locales = Locale.getAvailableLocales();
0100:                for (int i = 0; i < locales.length; i++) {
0101:                    String country = locales[i].getCountry();
0102:                    if (country.length() > 0)
0103:                        _countryCodes.add(country);
0104:                }
0105:            }
0106:
0107:            private static class ValidationContext {
0108:                private XPDLPackage pkg;
0109:                private Stack _prefixes = new Stack();
0110:                private Map _uniqueIds = new HashMap();
0111:                private String _prefix;
0112:                private List _errors;
0113:                private List _warnings;
0114:
0115:                ValidationContext(XPDLPackage pkg) {
0116:                    this .pkg = pkg;
0117:                }
0118:
0119:                void popPrefix() {
0120:                    _prefixes.pop();
0121:                    generatePrefix();
0122:                }
0123:
0124:                String peekPrefix() {
0125:                    return (String) _prefixes.peek();
0126:                }
0127:
0128:                void pushPrefix(String prefix) {
0129:                    _prefixes.push(prefix);
0130:                    generatePrefix();
0131:                }
0132:
0133:                private void generatePrefix() {
0134:                    StringBuffer sb = new StringBuffer();
0135:                    for (Iterator iter = _prefixes.iterator(); iter.hasNext();) {
0136:                        sb.append('/');
0137:                        sb.append(iter.next());
0138:                    }
0139:                    _prefix = sb.toString();
0140:                }
0141:
0142:                void checkValidUniqueId(Object src, String prefix,
0143:                        String priKey, String id, Object obj) {
0144:
0145:                    checkValidUniqueId(src, prefix, priKey, null, null, id, obj);
0146:                }
0147:
0148:                void checkValidUniqueId(Object src, String prefix,
0149:                        String priKey, String secKey, String id, Object obj) {
0150:
0151:                    checkValidUniqueId(src, prefix, priKey, secKey, null, id,
0152:                            obj);
0153:                }
0154:
0155:                void checkValidUniqueId(Object src, String prefix,
0156:                        String priKey, String secKey, String tertKey,
0157:                        String id, Object obj) {
0158:
0159:                    String owner = prefix != null ? prefix : peekPrefix();
0160:                    if (prefix == null)
0161:                        prefix = "";
0162:                    if (id == null || id.trim().length() == 0) {
0163:                        addError(src, ID_MUST_BE_SPECIFIED,
0164:                                new Object[] { owner }, prefix
0165:                                        + "/Id must be specified");
0166:                    } else {
0167:                        // Make sure this is a valid NMTOKEN string.
0168:                        if (!isValidNMToken(id)) {
0169:                            addError(src, INVALID_NMTOKEN,
0170:                                    new Object[] { owner }, prefix
0171:                                            + "/Id is not a valid NMTOKEN");
0172:                        }
0173:
0174:                        // Make sure it isn't already in use.
0175:                        Map uniqueIds = getUniqueIds(priKey);
0176:                        boolean exists = uniqueIds.containsKey(id);
0177:                        if (!exists && secKey != null)
0178:                            exists = getUniqueIds(secKey).containsKey(id);
0179:                        if (!exists && tertKey != null)
0180:                            exists = getUniqueIds(tertKey).containsKey(id);
0181:                        if (exists) {
0182:                            addError(
0183:                                    src,
0184:                                    ID_ALREADY_DEFINED,
0185:                                    new Object[] { owner },
0186:                                    prefix
0187:                                            + " is already defined. Remove the duplicate entity or assign it a unique ID.");
0188:                        } else {
0189:                            uniqueIds.put(id, obj);
0190:                        }
0191:                    }
0192:                }
0193:
0194:                /**
0195:                 * Checks whether a string is a valid XML Schema
0196:                 * <a href="http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken">
0197:                 * NMTOKEN</a>.
0198:                 *
0199:                 * @param id The string to check.
0200:                 * @return <code>true</code> if it is a valid NMTOKEN.
0201:                 */
0202:                private boolean isValidNMToken(String id) {
0203:                    // TODO: Handle Unicode CombiningChar and Extender
0204:                    // CombiningChar    ::=    [#x0300-#x0345] | [#x0360-#x0361] |
0205:                    // [#x0483-#x0486] | [#x0591-#x05A1] | [#x05A3-#x05B9] |
0206:                    // [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 |
0207:                    // [#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] |
0208:                    // [#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] |
0209:                    // [#x0901-#x0903] | #x093C | [#x093E-#x094C] | #x094D |
0210:                    // [#x0951-#x0954] | [#x0962-#x0963] | [#x0981-#x0983] | #x09BC |
0211:                    // #x09BE | #x09BF | [#x09C0-#x09C4] | [#x09C7-#x09C8] |
0212:                    // [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | #x0A3C |
0213:                    // #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] |
0214:                    // [#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC |
0215:                    // [#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] |
0216:                    // [#x0B01-#x0B03] | #x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] |
0217:                    // [#x0B4B-#x0B4D] | [#x0B56-#x0B57] | [#x0B82-#x0B83] |
0218:                    // [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | [#x0BCA-#x0BCD] | #x0BD7 |
0219:                    // [#x0C01-#x0C03] | [#x0C3E-#x0C44] | [#x0C46-#x0C48] |
0220:                    // [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] |
0221:                    // [#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] |
0222:                    // [#x0CD5-#x0CD6] | [#x0D02-#x0D03] | [#x0D3E-#x0D43] |
0223:                    // [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | #x0D57 | #x0E31 |
0224:                    // [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | [#x0EB4-#x0EB9] |
0225:                    // [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | #x0F35 |
0226:                    // #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] |
0227:                    // [#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] |
0228:                    // [#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 |
0229:                    // [#x302A-#x302F] | #x3099 | #x309A
0230:                    //
0231:                    // Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 |
0232:                    // #x0E46 | #x0EC6 | #x3005 | [#x3031-#x3035] | [#x309D-#x309E] |
0233:                    // [#x30FC-#x30FE
0234:                    //
0235:                    // NameChar ::= Letter | Digit  | '.' | '-' | '_' | ':' |
0236:                    // CombiningChar | Extender
0237:                    //
0238:                    // Nmtoken ::= (NameChar)+
0239:
0240:                    boolean valid = true;
0241:                    for (int i = 0, n = id.length(); i < n; i++) {
0242:                        char c = id.charAt(i);
0243:                        if (!Character.isLetterOrDigit(c) && c != '.'
0244:                                && c != '-' && c != '_') {
0245:
0246:                            valid = false;
0247:                            break;
0248:                        }
0249:                    }
0250:                    return valid;
0251:                }
0252:
0253:                void checkValidIdRef(Object src, String prefix,
0254:                        String primaryKey, String refId) {
0255:
0256:                    checkValidIdRef(src, prefix, primaryKey, null, null, refId);
0257:                }
0258:
0259:                Object checkValidIdRef(Object src, String prefix,
0260:                        String primaryKey, String secondaryKey, String refId) {
0261:
0262:                    return checkValidIdRef(src, prefix, primaryKey,
0263:                            secondaryKey, null, refId);
0264:                }
0265:
0266:                Object checkValidIdRef(Object src, String prefix,
0267:                        String primaryKey, String secondaryKey,
0268:                        String tertiaryKey, String refId) {
0269:
0270:                    String owner = prefix != null ? prefix : peekPrefix();
0271:                    if (prefix == null)
0272:                        prefix = "";
0273:                    Object obj = getUniqueIds(primaryKey).get(refId);
0274:                    if (obj == null && secondaryKey != null)
0275:                        obj = getUniqueIds(secondaryKey).get(refId);
0276:                    if (obj == null && tertiaryKey != null)
0277:                        obj = getUniqueIds(tertiaryKey).get(refId);
0278:                    if (obj == null) {
0279:                        addError(src, UNDEFINED_REFERENCE, new Object[] {
0280:                                owner, primaryKey, refId }, prefix
0281:                                + " references an undefined " + primaryKey
0282:                                + '[' + refId + ']');
0283:                    }
0284:                    return obj;
0285:                }
0286:
0287:                void resetUniqueId(String key) {
0288:                    getUniqueIds(key).clear();
0289:                }
0290:
0291:                boolean checkNotNull(Object src, String prefix, Object obj) {
0292:                    if (prefix == null)
0293:                        prefix = "";
0294:                    if (obj instanceof  String) {
0295:                        String s = ((String) obj).trim();
0296:                        if (s.length() == 0)
0297:                            obj = null;
0298:                    }
0299:                    boolean notNull = obj != null;
0300:                    if (!notNull) {
0301:                        addError(src, PROPERTY_MISSING, new Object[] {
0302:                                peekPrefix(), prefix }, prefix
0303:                                + " must be specified");
0304:                    }
0305:                    return notNull;
0306:                }
0307:
0308:                boolean checkEQ(Object src, String prefix, String property,
0309:                        int expected, int actual) {
0310:
0311:                    if (prefix == null)
0312:                        prefix = "";
0313:                    boolean eq = actual == expected;
0314:                    if (!eq) {
0315:                        addError(src, COUNT_INCORRECT, new Object[] {
0316:                                peekPrefix(), property, new Integer(expected),
0317:                                new Integer(actual) }, prefix + ": expected <"
0318:                                + expected + ">, actual <" + actual + '>');
0319:                    }
0320:                    return eq;
0321:                }
0322:
0323:                void checkGE(Object src, String prefix, String property,
0324:                        int expected, int actual) {
0325:
0326:                    if (prefix == null)
0327:                        prefix = "";
0328:                    boolean ge = actual >= expected;
0329:                    if (!ge) {
0330:                        addError(src, PROPERTY_VALUE_TOO_LOW, new Object[] {
0331:                                peekPrefix(), property, new Integer(expected),
0332:                                new Integer(actual) }, prefix + ": expected <"
0333:                                + expected + ">, actual <" + actual + '>');
0334:                    }
0335:                }
0336:
0337:                public void checkAssignable(Object src, String prefix,
0338:                        Type toType, Type fromType) {
0339:
0340:                    if (!toType.isAssignableFrom(fromType)) {
0341:                        addError(src, UNSUPPORTED_TYPE_CONVERSION,
0342:                                new Object[] { fromType, toType },
0343:                                "Unsupported type conversion: from <"
0344:                                        + fromType + "> to <" + toType + '>');
0345:                    }
0346:                }
0347:
0348:                void addError(Object src, int msgCode, Object[] args, String msg) {
0349:                    if (_errors == null)
0350:                        _errors = new ArrayList();
0351:                    _errors.add(new ValidationError(ValidationError.TYPE_ERROR,
0352:                            msgCode, args, src, _prefix + msg));
0353:                }
0354:
0355:                void addWarning(Object src, int msgCode, Object[] args,
0356:                        String msg) {
0357:                    if (_warnings == null)
0358:                        _warnings = new ArrayList();
0359:                    _warnings.add(new ValidationError(
0360:                            ValidationError.TYPE_WARNING, msgCode, args, src,
0361:                            _prefix + msg));
0362:                }
0363:
0364:                ValidationError[] getErrors() {
0365:                    return _errors == null ? null : (ValidationError[]) _errors
0366:                            .toArray(new ValidationError[_errors.size()]);
0367:                }
0368:
0369:                ValidationError[] getWarnings() {
0370:                    return _warnings == null ? null
0371:                            : (ValidationError[]) _warnings
0372:                                    .toArray(new ValidationError[_warnings
0373:                                            .size()]);
0374:                }
0375:
0376:                private Map getUniqueIds(String key) {
0377:                    Map ids = (Map) _uniqueIds.get(key);
0378:                    if (ids == null) {
0379:                        ids = new HashMap();
0380:                        _uniqueIds.put(key, ids);
0381:                    }
0382:                    return ids;
0383:                }
0384:            }
0385:
0386:            static {
0387:                for (int i = 0; i < DEFAULTS.length; i++) {
0388:                    String[] entry = DEFAULTS[i];
0389:                    _defaultProps.setProperty(entry[0], entry[1]);
0390:                }
0391:            }
0392:
0393:            public static void main(String[] args) {
0394:                try {
0395:                    XPDLParser parser = new Dom4JXPDLParser();
0396:                    if (args.length == 0)
0397:                        usage();
0398:                    int i = 0;
0399:                    Properties props = null;
0400:                    if (args[i].startsWith("-props")) {
0401:                        String propfile = args[i++];
0402:                        if (i == args.length)
0403:                            usage();
0404:                        props = new Properties();
0405:                        InputStream in = new FileInputStream(propfile);
0406:                        props.load(in);
0407:                        in.close();
0408:                    }
0409:                    PackageValidator validator = new PackageValidator(props);
0410:                    for (; i < args.length; i++) {
0411:                        String src = args[i];
0412:                        Reader rdr = new FileReader(src);
0413:                        XPDLPackage pkg = parser.parse(rdr);
0414:                        rdr.close();
0415:                        ValidationError[] errors = validator.validate(pkg,
0416:                                false);
0417:                        if (errors == null)
0418:                            System.out
0419:                                    .println(src + " is a valid XPDL package");
0420:                        else {
0421:                            System.err.println(src + " contains errors:\n");
0422:                            for (int j = 0; j < errors.length; j++)
0423:                                System.err.println(errors[j].getMessage());
0424:                            System.err.println("\n" + errors.length
0425:                                    + " errors\n");
0426:                        }
0427:                        System.out.println();
0428:                    }
0429:                } catch (Exception e) {
0430:                    _logger.error(e);
0431:                    System.exit(1);
0432:                }
0433:            }
0434:
0435:            private static void usage() {
0436:                System.out
0437:                        .println("usage: java org.obe.client.api.xpdl.PackageValidator [-props propfile] file...");
0438:                System.exit(1);
0439:            }
0440:
0441:            public PackageValidator() {
0442:            }
0443:
0444:            public PackageValidator(Properties props) {
0445:                if (props != null)
0446:                    _props.putAll(props);
0447:            }
0448:
0449:            public String getProperty(String key) {
0450:                return _props.getProperty(key);
0451:            }
0452:
0453:            public Object setProperty(String key, String value) {
0454:                return _props.setProperty(key, value);
0455:            }
0456:
0457:            public ValidationError[] validate(XPDLPackage pkg,
0458:                    boolean throwException) throws InvalidPackageException {
0459:
0460:                // Make sure all transitions connect to their associated activities.
0461:                for (int i = 0, n = pkg.getWorkflowProcess().length; i < n; i++)
0462:                    pkg.getWorkflowProcess(i).resolveReferences();
0463:
0464:                ValidationContext ctx = new ValidationContext(pkg);
0465:                checkPackage(ctx);
0466:
0467:                ValidationError[] errors = ctx.getErrors();
0468:                if (errors != null && throwException) {
0469:                    RedefinableHeader redefinableHeader = pkg
0470:                            .getRedefinableHeader();
0471:                    PublicationStatus publicationStatus = redefinableHeader == null ? null
0472:                            : redefinableHeader.getPublicationStatus();
0473:                    if (publicationStatus != PublicationStatus.UNDER_REVISION)
0474:                        throw new InvalidPackageException(pkg.getId(), errors);
0475:                }
0476:                return errors;
0477:            }
0478:
0479:            private void checkPackage(ValidationContext ctx) {
0480:                XPDLPackage pkg = ctx.pkg;
0481:                ctx.pushPrefix("Package[" + pkg.getId() + ']');
0482:                ctx.checkValidUniqueId(pkg, null, XPDLNames.PACKAGE, pkg
0483:                        .getId(), pkg);
0484:                checkPackageHeader(ctx);
0485:                checkRedefinableHeader(pkg.getRedefinableHeader(), ctx);
0486:                checkConformanceClass(ctx);
0487:                checkScript(ctx);
0488:                checkExternalPackages(ctx);
0489:                checkTypeDeclarations(ctx);
0490:                checkParticipants(pkg.getParticipant(), true, ctx);
0491:                checkApplications(pkg.getApplication(), true, ctx);
0492:                checkDataFields(pkg.getDataField(), true, ctx);
0493:                checkWorkflows(ctx);
0494:                ctx.popPrefix();
0495:            }
0496:
0497:            private void checkPackageHeader(ValidationContext ctx) {
0498:                ctx.pushPrefix(XPDLNames.PACKAGE_HEADER);
0499:                PackageHeader hdr = ctx.pkg.getPackageHeader();
0500:                ctx.checkNotNull(hdr, "/XPDLVersion", hdr.getXPDLVersion());
0501:                ctx.checkNotNull(hdr, "/Vendor", hdr.getVendor());
0502:                ctx.checkNotNull(hdr, "/Created", hdr.getCreated());
0503:                ctx.popPrefix();
0504:            }
0505:
0506:            private void checkRedefinableHeader(RedefinableHeader hdr,
0507:                    ValidationContext ctx) {
0508:
0509:                ctx.pushPrefix(XPDLNames.REDEFINABLE_HEADER);
0510:                if (hdr != null) {
0511:                    // TODO: enable codepage check in JDK1.4 only.
0512:                    //        String codepage = hdr.getCodepage();
0513:                    //        if (codepage != null && Charset.isSupported(codepage)) {
0514:                    //            ctx.addError(hdr, UNSUPPORTED_CODEPAGE, new Object[]{codepage},
0515:                    //                "Unsupported codepage: " + codepage);
0516:                    //        }
0517:
0518:                    String country = hdr.getCountrykey();
0519:                    if (country != null && !_countryCodes.contains(country)) {
0520:                        ctx.addWarning(hdr, UNSUPPORTED_COUNTRY,
0521:                                new Object[] { country },
0522:                                "Unsupported country: " + country);
0523:                    }
0524:                }
0525:                ctx.popPrefix();
0526:            }
0527:
0528:            // Ensure a minimum graph conformance level, and that the activity net
0529:            // does actually conform to that level.
0530:            private void checkConformanceClass(ValidationContext ctx) {
0531:                ConformanceClass cc = ctx.pkg.getConformanceClass();
0532:                GraphConformance gc = cc == null ? null : cc
0533:                        .getGraphConformance();
0534:                if (gc == null)
0535:                    gc = GraphConformance.NON_BLOCKED;
0536:                String gcl = getProperty(GRAPH_CONFORMANCE_MIN_PROP);
0537:                ctx.checkGE(ctx.pkg,
0538:                        " Graph conformance level must be at least " + gcl,
0539:                        XPDLNames.GRAPH_CONFORMANCE, GraphConformance.valueOf(
0540:                                gcl).value(), gc.value());
0541:                // TODO: verify activity nets conform to declared graph conformance class.
0542:            }
0543:
0544:            private void checkScript(ValidationContext ctx) {
0545:                Script script = ctx.pkg.getScript();
0546:                if (script != null) {
0547:                    String type = script.getType();
0548:                    ctx.pushPrefix("Script[" + type + ']');
0549:                    if (type == null || type.startsWith("text/")
0550:                            && !type.startsWith("text/x-")
0551:                            && !type.startsWith("text/xml/x-")) {
0552:
0553:                        ctx
0554:                                .addError(
0555:                                        ctx.pkg,
0556:                                        INVALID_SCRIPT,
0557:                                        new Object[] { script },
0558:                                        " is not a valid script declaration. The script type is"
0559:                                                + " an extended MIME Media Type and must start with "
0560:                                                + "\"text/x-\" or \"text/xml/x-\"");
0561:                    }
0562:                    ctx.popPrefix();
0563:                }
0564:            }
0565:
0566:            private void checkExternalPackages(ValidationContext ctx) {
0567:                ExternalPackage[] pkgs = ctx.pkg.getExternalPackage();
0568:                for (int i = 0; i < pkgs.length; i++) {
0569:                    ExternalPackage pkg = pkgs[i];
0570:                    ctx.checkNotNull(ctx.pkg,
0571:                            "/ExternalPackages/ExternalPackage[" + i
0572:                                    + "]/@href", pkg.getHref());
0573:                }
0574:            }
0575:
0576:            private void checkTypeDeclarations(ValidationContext ctx) {
0577:                ctx.resetUniqueId(XPDLNames.TYPE_DECLARATION);
0578:                TypeDeclaration[] typeDeclarations = ctx.pkg
0579:                        .getTypeDeclaration();
0580:                if (typeDeclarations != null) {
0581:                    for (int i = 0, n = typeDeclarations.length; i < n; i++)
0582:                        checkTypeDeclaration(typeDeclarations[i], ctx);
0583:                }
0584:            }
0585:
0586:            private void checkTypeDeclaration(TypeDeclaration typeDecl,
0587:                    ValidationContext ctx) {
0588:
0589:                ctx.pushPrefix("TypeDeclaration[" + typeDecl.getId() + ']');
0590:                ctx.checkValidUniqueId(typeDecl, null,
0591:                        XPDLNames.TYPE_DECLARATION, typeDecl.getId(), typeDecl);
0592:                Type type = typeDecl.getType();
0593:                if (type == null) {
0594:                    ctx
0595:                            .addError(
0596:                                    ctx.pkg,
0597:                                    INVALID_TYPE_DECL,
0598:                                    null,
0599:                                    typeDecl
0600:                                            + " is not a valid type declaration: a type is required.");
0601:                }
0602:                ctx.popPrefix();
0603:            }
0604:
0605:            private void checkParticipants(Participant[] participants,
0606:                    boolean pkgLevel, ValidationContext ctx) {
0607:
0608:                String pri = pkgLevel ? PKG_PARTICIPANT : XPDLNames.PARTICIPANT;
0609:                String sec = pkgLevel ? null : PKG_PARTICIPANT;
0610:                ctx.resetUniqueId(pri);
0611:                if (participants != null) {
0612:                    for (int i = 0, n = participants.length; i < n; i++) {
0613:                        Participant particip = participants[i];
0614:                        ctx.checkValidUniqueId(particip, "/Participant["
0615:                                + particip.getId() + ']', pri, sec, particip
0616:                                .getId(), particip);
0617:                    }
0618:                }
0619:            }
0620:
0621:            private void checkApplications(Application[] applications,
0622:                    boolean pkgLevel, ValidationContext ctx) {
0623:
0624:                String pri = pkgLevel ? PKG_APPLICATION : XPDLNames.APPLICATION;
0625:                String sec = pkgLevel ? null : PKG_APPLICATION;
0626:                ctx.resetUniqueId(pri);
0627:                if (applications != null) {
0628:                    for (int i = 0, n = applications.length; i < n; i++) {
0629:                        Application app = applications[i];
0630:                        ctx.pushPrefix("Application[" + app.getId() + ']');
0631:                        ctx.checkValidUniqueId(app, null, pri, sec,
0632:                                app.getId(), app);
0633:                        checkFormalParameters(app.getFormalParameter(), false,
0634:                                ctx);
0635:                        ctx.popPrefix();
0636:                    }
0637:                }
0638:            }
0639:
0640:            private void checkFormalParameters(FormalParameter[] parameters,
0641:                    boolean wfLevel, ValidationContext ctx) {
0642:
0643:                String key = wfLevel ? WORKFLOW_FORMAL_PARAMETER
0644:                        : XPDLNames.FORMAL_PARAMETER;
0645:                ctx.resetUniqueId(key);
0646:                if (parameters != null) {
0647:                    for (int i = 0, n = parameters.length; i < n; i++) {
0648:                        FormalParameter parm = parameters[i];
0649:                        ctx.checkValidUniqueId(parm, "/FormalParameter["
0650:                                + parm.getId() + ']', key, parm.getId(), parm);
0651:                    }
0652:                }
0653:            }
0654:
0655:            private void checkDataFields(DataField[] dataFields,
0656:                    boolean pkgLevel, ValidationContext ctx) {
0657:
0658:                ctx.resetUniqueId(pkgLevel ? PKG_DATA_FIELD
0659:                        : XPDLNames.DATA_FIELD);
0660:                if (dataFields != null) {
0661:                    for (int i = 0, n = dataFields.length; i < n; i++)
0662:                        checkDataField(dataFields[i], pkgLevel, ctx);
0663:                }
0664:            }
0665:
0666:            private void checkDataField(DataField dataField, boolean pkgLevel,
0667:                    ValidationContext ctx) {
0668:
0669:                String pri = pkgLevel ? PKG_DATA_FIELD : XPDLNames.DATA_FIELD;
0670:                String sec = pkgLevel ? null : WORKFLOW_FORMAL_PARAMETER;
0671:                String tert = pkgLevel ? null : PKG_DATA_FIELD;
0672:                String dataFieldId = dataField.getId();
0673:                ctx.pushPrefix("DataField[" + dataFieldId + ']');
0674:                ctx.checkValidUniqueId(dataField, null, pri, sec, tert,
0675:                        dataFieldId, dataField);
0676:                DataType dataType = dataField.getDataType();
0677:                Type type = dataType == null ? null : dataType.getType();
0678:                ctx.checkNotNull(dataField, "/Type", type);
0679:                ctx.popPrefix();
0680:                if (type instanceof  DeclaredType) {
0681:                    ctx.checkValidIdRef(dataField, "/Id",
0682:                            XPDLNames.TYPE_DECLARATION, ((DeclaredType) type)
0683:                                    .getId());
0684:                    //        } else if (type instanceof BasicType) {
0685:                    //        } else if (type instanceof SchemaType) {
0686:                    //        } else if (type instanceof ExternalReference) {
0687:                    //        } else if (type instanceof RecordType) {
0688:                    //        } else if (type instanceof UnionType) {
0689:                    //        } else if (type instanceof EnumerationType) {
0690:                    //        } else if (type instanceof ArrayType) {
0691:                    //        } else if (type instanceof ListType) {
0692:                }
0693:            }
0694:
0695:            private void checkWorkflows(ValidationContext ctx) {
0696:                ctx.resetUniqueId(XPDLNames.WORKFLOW_PROCESS);
0697:                WorkflowProcess[] workflowProcesses = ctx.pkg
0698:                        .getWorkflowProcess();
0699:                if (workflowProcesses != null) {
0700:                    for (int i = 0, n = workflowProcesses.length; i < n; i++)
0701:                        checkWorkflow(workflowProcesses[i], ctx);
0702:                }
0703:            }
0704:
0705:            private void checkWorkflow(WorkflowProcess workflow,
0706:                    ValidationContext ctx) {
0707:
0708:                ctx.resetUniqueId(XPDLNames.DATA_FIELD);
0709:                ctx.resetUniqueId(WORKFLOW_FORMAL_PARAMETER);
0710:                ctx.resetUniqueId(XPDLNames.ACTIVITY);
0711:                ctx.resetUniqueId(XPDLNames.TRANSITION);
0712:                String workflowId = workflow.getId();
0713:                ctx.pushPrefix("Workflow[" + workflowId + ']');
0714:                ctx.checkValidUniqueId(workflow, null,
0715:                        XPDLNames.WORKFLOW_PROCESS, workflowId, workflow);
0716:                checkProcessHeader(workflow, ctx);
0717:                checkRedefinableHeader(workflow.getRedefinableHeader(), ctx);
0718:                checkFormalParameters(workflow.getFormalParameter(), true, ctx);
0719:                checkDataFields(workflow.getDataField(), false, ctx);
0720:                checkParticipants(workflow.getParticipant(), false, ctx);
0721:                checkApplications(workflow.getApplication(), false, ctx);
0722:                checkActivitySets(workflow.getActivitySet(), ctx);
0723:                checkActivities(workflow, workflow.getActivity(), ctx);
0724:                checkTransitions(workflow.getTransition(), ctx);
0725:                ctx.popPrefix();
0726:            }
0727:
0728:            private void checkProcessHeader(WorkflowProcess workflow,
0729:                    ValidationContext ctx) {
0730:
0731:                ProcessHeader hdr = workflow.getProcessHeader();
0732:                Date validFrom = hdr.getValidFrom();
0733:                Date validTo = hdr.getValidTo();
0734:                if (validFrom != null && validTo != null
0735:                        && validTo.before(validFrom)) {
0736:                    ctx.addError(workflow, INVALID_FROM_TO_DATES, new Object[] {
0737:                            validFrom, validTo },
0738:                            "Invalid ValidFrom/ValidTo specification: "
0739:                                    + validFrom + '/' + validTo
0740:                                    + ". ValidFrom must pre-date ValidTo");
0741:                }
0742:            }
0743:
0744:            private void checkActivitySets(ActivitySet[] activitySets,
0745:                    ValidationContext ctx) {
0746:
0747:                ctx.resetUniqueId(XPDLNames.ACTIVITY_SET);
0748:                if (activitySets != null) {
0749:                    for (int i = 0, n = activitySets.length; i < n; i++)
0750:                        checkActivitySet(activitySets[i], ctx);
0751:                }
0752:            }
0753:
0754:            private void checkActivitySet(ActivitySet activitySet,
0755:                    ValidationContext ctx) {
0756:
0757:                String id = activitySet.getId();
0758:                ctx.pushPrefix("ActivitySet[" + id + ']');
0759:                ctx.checkValidUniqueId(activitySet, null,
0760:                        XPDLNames.ACTIVITY_SET, id, activitySet);
0761:                checkActivities(activitySet, activitySet.getActivity(), ctx);
0762:                checkTransitions(activitySet.getTransition(), ctx);
0763:                ctx.popPrefix();
0764:            }
0765:
0766:            private void checkActivities(Object src, Activity[] activities,
0767:                    ValidationContext ctx) {
0768:
0769:                if (activities != null) {
0770:                    boolean foundStart = false;
0771:                    boolean foundExit = false;
0772:                    for (int i = 0, n = activities.length; i < n; i++) {
0773:                        Activity activity = activities[i];
0774:                        checkActivity(activity, ctx);
0775:                        if (activity.isStartActivity())
0776:                            foundStart = true;
0777:                        if (activity.isExitActivity())
0778:                            foundExit = true;
0779:                    }
0780:                    if (!foundStart) {
0781:                        ctx
0782:                                .addError(
0783:                                        src,
0784:                                        START_ACTIVITY_REQUIRED,
0785:                                        new Object[] { ctx.peekPrefix() },
0786:                                        " must have at least one start activity (one with no afferent (inbound) transitions)");
0787:                    }
0788:                    if (!foundExit) {
0789:                        ctx
0790:                                .addError(
0791:                                        src,
0792:                                        EXIT_ACTIVITY_REQUIRED,
0793:                                        new Object[] { ctx.peekPrefix() },
0794:                                        " must have at least one exit activity (one with no efferent (outbound) transitions)");
0795:                    }
0796:                }
0797:            }
0798:
0799:            private void checkActivity(Activity activity, ValidationContext ctx) {
0800:                String activityId = activity.getId();
0801:                ctx.pushPrefix("Activity[" + activityId + ']');
0802:                ctx.checkValidUniqueId(activity, null, XPDLNames.ACTIVITY,
0803:                        activityId, activity);
0804:                String performer = activity.getPerformer();
0805:                if (performer != null) {
0806:                    StringTokenizer strTok = new StringTokenizer(performer, ",");
0807:                    while (strTok.hasMoreTokens()) {
0808:                        ctx.checkValidIdRef(activity, "/Performer",
0809:                                XPDLNames.PARTICIPANT, PKG_PARTICIPANT, strTok
0810:                                        .nextToken());
0811:                    }
0812:                }
0813:                int bodyCount = 0;
0814:                BlockActivity blk = activity.getBlockActivity();
0815:                if (blk != null) {
0816:                    String blockId = blk.getBlockId();
0817:                    if (ctx
0818:                            .checkNotNull(activity, "/BlockActivity/Id",
0819:                                    blockId)
0820:                            && blk.getActivitySet() == null) {
0821:
0822:                        ctx.addError(activity, UNDEFINED_ACTIVITY_SET,
0823:                                new Object[] { ctx.peekPrefix(), blockId },
0824:                                "/BlockActivity references an undefined ActivitySet["
0825:                                        + blockId + ']');
0826:                    }
0827:                    bodyCount++;
0828:                }
0829:                Implementation impl = activity.getImplementation();
0830:                if (impl != null) {
0831:                    ctx.pushPrefix(XPDLNames.IMPLEMENTATION);
0832:                    if (impl instanceof  NoImplementation) {
0833:                        // Nothing to check.
0834:                    } else if (impl instanceof  SubFlow) {
0835:                        SubFlow subFlow = (SubFlow) impl;
0836:                        String subFlowId = subFlow.getId();
0837:                        ctx.pushPrefix("SubFlow[" + subFlowId + ']');
0838:                        if (ctx.checkNotNull(subFlow, null, subFlowId)) {
0839:                            boolean found = false;
0840:                            for (int i = 0, n = ctx.pkg.getWorkflowProcess().length; i < n; i++) {
0841:
0842:                                WorkflowProcess workflow = ctx.pkg
0843:                                        .getWorkflowProcess(i);
0844:                                if (workflow.getId().equals(subFlowId)) {
0845:                                    checkActualParameters(subFlow, workflow
0846:                                            .getFormalParameter(), subFlow
0847:                                            .getActualParameter(), ctx);
0848:                                    found = true;
0849:                                    break;
0850:                                }
0851:                            }
0852:                            if (!found) {
0853:                                ctx.addError(activity, UNDEFINED_SUBPROCESS,
0854:                                        new Object[] { activityId, subFlowId },
0855:                                        " references an undefined WorkflowProcess["
0856:                                                + subFlowId + ']');
0857:                            }
0858:                        }
0859:                        ctx.popPrefix();
0860:                    } else if (impl instanceof  ToolSet) {
0861:                        ToolSet toolSet = (ToolSet) impl;
0862:                        for (int j = 0, n = toolSet.getTool().length; j < n; j++) {
0863:                            Tool tool = toolSet.getTool(j);
0864:                            String toolId = tool.getId();
0865:                            if (ctx.checkNotNull(tool, "/Tool/Id", toolId)) {
0866:                                ctx.pushPrefix("Tool[" + toolId + ']');
0867:                                Application app = (Application) ctx
0868:                                        .checkValidIdRef(tool, null,
0869:                                                XPDLNames.APPLICATION,
0870:                                                PKG_APPLICATION, toolId);
0871:                                ctx.checkNotNull(tool, "/Type", tool
0872:                                        .getToolType());
0873:                                if (app != null) {
0874:                                    ExternalReference extRef = app
0875:                                            .getExternalReference();
0876:                                    if (extRef == null) {
0877:                                        checkActualParameters(tool, app
0878:                                                .getFormalParameter(), tool
0879:                                                .getActualParameter(), ctx);
0880:                                    } else {
0881:                                        checkActualParameters(tool, extRef,
0882:                                                tool.getActualParameter(), ctx);
0883:                                    }
0884:                                }
0885:                                ctx.popPrefix();
0886:                            }
0887:                        }
0888:                    }
0889:                    bodyCount++;
0890:                    ctx.popPrefix();
0891:                }
0892:                if (activity.getRoute() != null) {
0893:                    if (performer != null)
0894:                        ctx.addError(activity, ROUTE_CANNOT_HAVE_PERFORMER,
0895:                                new Object[] { activityId },
0896:                                "/Route cannot have a Performer");
0897:                    bodyCount++;
0898:                }
0899:                if (bodyCount != 1) {
0900:                    ctx
0901:                            .addError(activity, ACTIVITY_BODY_MISSING,
0902:                                    new Object[] { activityId },
0903:                                    " must include only one of: Route, Implementation, or BlockActivity");
0904:                }
0905:
0906:                Deadline[] deadlines = activity.getDeadline();
0907:                if (deadlines != null) {
0908:                    Set deadlineExceptions = new HashSet();
0909:                    ctx.pushPrefix(XPDLNames.DEADLINE);
0910:                    int syncCount = 0;
0911:                    for (int i = 0, n = deadlines.length; i < n; i++) {
0912:                        Deadline deadline = deadlines[i];
0913:                        // TODO: validate condition.
0914:                        String condition = deadline.getDeadlineCondition();
0915:                        ctx.checkNotNull(deadline, "/Condition", condition);
0916:                        String exceptionName = deadline.getExceptionName();
0917:                        ctx.checkNotNull(deadline, "/Exception", exceptionName);
0918:                        deadlineExceptions.add(exceptionName);
0919:                        if (deadline.getExecutionType() == ExecutionType.SYNCHRONOUS
0920:                                && ++syncCount == 2) {
0921:
0922:                            ctx.addError(activity, MAX_ONE_SYNC_DEADLINE,
0923:                                    new Object[] { activityId },
0924:                                    " can only have one synchronous deadline");
0925:                        }
0926:                    }
0927:                    // Check that all deadline exceptions are handled.
0928:                    Map transitions = activity.getEfferentTransitions();
0929:                    if (transitions != null) {
0930:                        for (Iterator iter = transitions.values().iterator(); iter
0931:                                .hasNext();) {
0932:
0933:                            Transition transition = (Transition) iter.next();
0934:                            Condition condition = transition.getCondition();
0935:                            if (condition != null) {
0936:                                ConditionType type = condition.getType();
0937:                                if (type == ConditionType.DEFAULTEXCEPTION) {
0938:                                    deadlineExceptions.clear();
0939:                                    break;
0940:                                } else if (type == ConditionType.EXCEPTION) {
0941:                                    deadlineExceptions.remove(condition
0942:                                            .getValue());
0943:                                }
0944:                            }
0945:                            if (transition.getExecution() != null
0946:                                    && deadlines.length > 0) {
0947:
0948:                                ctx.addError(activity, INCOMPATIBLE_TRANSITION,
0949:                                        new Object[] { activityId,
0950:                                                transition.getId() },
0951:                                        " is incompatible with Transition["
0952:                                                + transition.getId()
0953:                                                + "]/ExtendedAttribute["
0954:                                                + XPDLNames.EXECUTION + ']');
0955:                            }
0956:                        }
0957:                    }
0958:                    for (Iterator iter = deadlineExceptions.iterator(); iter
0959:                            .hasNext();) {
0960:                        String exception = (String) iter.next();
0961:                        ctx
0962:                                .addError(
0963:                                        activity,
0964:                                        EXCEPTION_NOT_HANDLED,
0965:                                        new Object[] { activityId, exception },
0966:                                        "/ExceptionName["
0967:                                                + exception
0968:                                                + "] is not handled by any efferent (outbound) transition");
0969:                    }
0970:                    ctx.popPrefix();
0971:                }
0972:
0973:                TransitionRestriction[] restrictions = activity
0974:                        .getTransitionRestriction();
0975:                SplitType splitType = null;
0976:                boolean joinFound = false;
0977:                boolean splitFound = false;
0978:                boolean otherwiseFound = false;
0979:                boolean conditionFound = false;
0980:                boolean nonConditionFound = false;
0981:                if (restrictions != null) {
0982:                    ctx.pushPrefix(XPDLNames.TRANSITION_RESTRICTION);
0983:                    for (int i = 0, n = restrictions.length; i < n; i++) {
0984:                        TransitionRestriction restriction = restrictions[i];
0985:                        Join join = restriction.getJoin();
0986:                        if (join != null) {
0987:                            // Only one join is permitted.
0988:                            if (joinFound) {
0989:                                ctx
0990:                                        .addError(
0991:                                                activity,
0992:                                                TRANSITION_RESTRICTIONS_ONLY_ONE_JOIN,
0993:                                                new Object[] { activityId },
0994:                                                " TransitionRestrictions can only contain one join.");
0995:                            }
0996:                            joinFound = true;
0997:                        }
0998:                        Split split = restriction.getSplit();
0999:                        if (split != null) {
1000:                            // Only one split is permitted.
1001:                            if (splitFound) {
1002:                                ctx
1003:                                        .addError(
1004:                                                activity,
1005:                                                TRANSITION_RESTRICTIONS_ONLY_ONE_SPLIT,
1006:                                                new Object[] { activityId },
1007:                                                " TransitionRestrictions can only contain one split in OBE (XPDL permits more, but does not define the semantics).");
1008:                            }
1009:                            splitFound = true;
1010:                            splitType = split.getType();
1011:                            ctx.checkNotNull(split, "/Split/Type", splitType);
1012:                            if (splitType == SplitType.XOR) {
1013:                                ctx.pushPrefix("Split[XOR]");
1014:                                String[] transitionRefs = split
1015:                                        .getTransitionReference();
1016:                                if (transitionRefs == null) {
1017:                                    ctx
1018:                                            .addError(
1019:                                                    activity,
1020:                                                    SPLIT_MISSING_REFERENCES,
1021:                                                    new Object[] { activityId },
1022:                                                    " does not reference any transitions");
1023:                                } else {
1024:                                    // TransitionRefs must refer to valid transitions.
1025:                                    for (int j = 0, p = transitionRefs.length; j < p; j++) {
1026:
1027:                                        String transitionId = transitionRefs[j];
1028:                                        if (!activity.getEfferentTransitions()
1029:                                                .containsKey(transitionId)) {
1030:
1031:                                            ctx
1032:                                                    .addError(
1033:                                                            activity,
1034:                                                            INVALID_TRANSITION_REF,
1035:                                                            new Object[] {
1036:                                                                    activityId,
1037:                                                                    transitionId },
1038:                                                            "/TransitionRef["
1039:                                                                    + transitionId
1040:                                                                    + "] references non-efferent (outbound) Transition");
1041:                                        }
1042:                                    }
1043:                                    // Efferent transitions must have TransitionRefs
1044:                                    // (other than exception and event transitions).
1045:                                    for (Iterator iter = activity
1046:                                            .getEfferentTransitions().values()
1047:                                            .iterator(); iter.hasNext();) {
1048:
1049:                                        Transition transition = (Transition) iter
1050:                                                .next();
1051:                                        Condition condition = transition
1052:                                                .getCondition();
1053:                                        ConditionType conditionType = condition == null ? null
1054:                                                : condition.getType();
1055:                                        Event event = transition.getEvent();
1056:                                        if (event == null) {
1057:                                            if (conditionType == null
1058:                                                    || conditionType == ConditionType.CONDITION
1059:                                                    || conditionType == ConditionType.OTHERWISE) {
1060:
1061:                                                if (conditionType == null)
1062:                                                    nonConditionFound = true;
1063:                                                else if (conditionType == ConditionType.CONDITION)
1064:                                                    conditionFound = true;
1065:
1066:                                                String transitionId = transition
1067:                                                        .getId();
1068:                                                boolean found = false;
1069:                                                for (int k = 0; k < transitionRefs.length; k++) {
1070:                                                    if (transitionRefs[k]
1071:                                                            .equals(transitionId)) {
1072:
1073:                                                        found = true;
1074:                                                        break;
1075:                                                    }
1076:                                                }
1077:                                                if (!found) {
1078:                                                    ctx
1079:                                                            .addError(
1080:                                                                    activity,
1081:                                                                    TRANSITION_REF_MISSING,
1082:                                                                    new Object[] {
1083:                                                                            activityId,
1084:                                                                            transitionId },
1085:                                                                    " does not reference Transition["
1086:                                                                            + transitionId
1087:                                                                            + ']');
1088:                                                }
1089:                                            }
1090:                                        } else {
1091:                                            if (conditionType == ConditionType.DEFAULTEXCEPTION
1092:                                                    || conditionType == ConditionType.EXCEPTION
1093:                                                    || conditionType == ConditionType.OTHERWISE) {
1094:
1095:                                                ctx
1096:                                                        .addError(
1097:                                                                transition,
1098:                                                                EVENT_TRANSITION_MISMATCH,
1099:                                                                new Object[] {
1100:                                                                        transition
1101:                                                                                .getId(),
1102:                                                                        conditionType },
1103:                                                                " OBE event transitions cannot be "
1104:                                                                        + "used in conjunction with an XPDL "
1105:                                                                        + "transition type of "
1106:                                                                        + conditionType);
1107:                                            }
1108:                                        }
1109:                                        if (conditionType == ConditionType.OTHERWISE) {
1110:                                            if (otherwiseFound) {
1111:                                                ctx
1112:                                                        .addError(
1113:                                                                transition,
1114:                                                                OTHERWISE_ALREADY_DEFINED,
1115:                                                                new Object[] { activityId },
1116:                                                                OTHERWISE_TRANSITION_ALREADY_DEFINED);
1117:                                            }
1118:                                            otherwiseFound = true;
1119:                                        }
1120:                                    }
1121:                                }
1122:                                ctx.popPrefix();
1123:                            } else {
1124:                                for (Iterator iter = activity
1125:                                        .getEfferentTransitions().values()
1126:                                        .iterator(); iter.hasNext();) {
1127:
1128:                                    Transition transition = (Transition) iter
1129:                                            .next();
1130:                                    Condition condition = transition
1131:                                            .getCondition();
1132:                                    ConditionType transitionType = condition == null ? null
1133:                                            : condition.getType();
1134:                                    if (transitionType == ConditionType.OTHERWISE) {
1135:                                        if (otherwiseFound) {
1136:                                            ctx
1137:                                                    .addError(
1138:                                                            transition,
1139:                                                            OTHERWISE_ALREADY_DEFINED,
1140:                                                            new Object[] { activityId },
1141:                                                            OTHERWISE_TRANSITION_ALREADY_DEFINED);
1142:                                        }
1143:                                        otherwiseFound = true;
1144:                                    }
1145:                                }
1146:                            }
1147:                        }
1148:                    }
1149:                    ctx.popPrefix();
1150:                }
1151:                if (!joinFound) {
1152:                    int count = activity.getAfferentTransitions().size();
1153:                    if (count > 1) {
1154:                        ctx
1155:                                .addError(
1156:                                        activity,
1157:                                        JOIN_REQUIRED,
1158:                                        new Object[] { activityId,
1159:                                                new Integer(count) },
1160:                                        " has "
1161:                                                + count
1162:                                                + " afferent (inbound) transitions, and therefore requires a Join");
1163:                    }
1164:                }
1165:                if (!splitFound) {
1166:                    int count = 0;
1167:                    for (Iterator iter = activity.getEfferentTransitions()
1168:                            .values().iterator(); iter.hasNext();) {
1169:
1170:                        Transition transition = (Transition) iter.next();
1171:                        Condition condition = transition.getCondition();
1172:                        ConditionType transitionType = condition == null ? null
1173:                                : condition.getType();
1174:                        if (transition.getEvent() == null
1175:                                && (transitionType == null
1176:                                        || transitionType == ConditionType.CONDITION || transitionType == ConditionType.OTHERWISE)) {
1177:
1178:                            count++;
1179:                        }
1180:                    }
1181:                    if (count > 1) {
1182:                        ctx
1183:                                .addError(
1184:                                        activity,
1185:                                        SPLIT_REQUIRED,
1186:                                        new Object[] { activityId,
1187:                                                new Integer(count) },
1188:                                        " has "
1189:                                                + count
1190:                                                + " regular efferent (outbound) transitions, and therefore requires a Split");
1191:                    }
1192:                }
1193:
1194:                // XOR-Splits in FULL_BLOCKED workflows must contain an OTHERWISE
1195:                // or unconditional transition.
1196:                if (splitType == SplitType.XOR && conditionFound
1197:                        && !nonConditionFound && !otherwiseFound) {
1198:                    ConformanceClass conformanceClass = activity
1199:                            .getWorkflowProcess().getPackage()
1200:                            .getConformanceClass();
1201:                    boolean fullBlocked = conformanceClass != null
1202:                            && conformanceClass.getGraphConformance() == GraphConformance.FULL_BLOCKED;
1203:
1204:                    if (fullBlocked) {
1205:                        ctx
1206:                                .addError(
1207:                                        activity,
1208:                                        OTHERWISE_REQUIRED,
1209:                                        new Object[] { activityId },
1210:                                        " is in a FULL_BLOCKED WorkflowProcess and has an "
1211:                                                + "XOR-Split, and therefore requires an OTHERWISE or "
1212:                                                + "unconditional transition.");
1213:                    }
1214:                }
1215:                ctx.popPrefix();
1216:            }
1217:
1218:            private void checkActualParameters(Object src,
1219:                    ExternalReference extRef, ActualParameter[] actualParms,
1220:                    ValidationContext ctx) {
1221:
1222:                // TODO: Retrieve external reference and check parameters against it.
1223:            }
1224:
1225:            private void checkActualParameters(Object src,
1226:                    FormalParameter[] formalParms,
1227:                    ActualParameter[] actualParms, ValidationContext ctx) {
1228:
1229:                int fpCount = formalParms == null ? 0 : formalParms.length;
1230:                int apCount = actualParms == null ? 0 : actualParms.length;
1231:                boolean ok = ctx.checkEQ(src,
1232:                        " formal and actual parameter counts differ",
1233:                        "FormalParameters", fpCount, apCount);
1234:                if (ok) {
1235:                    for (int i = 0; i < fpCount; i++) {
1236:                        FormalParameter fp = formalParms[i];
1237:                        ActualParameter ap = actualParms[i];
1238:                        int pmode = fp.getMode() != null ? fp.getMode().value()
1239:                                : ParameterMode.IN_INT;
1240:                        switch (pmode) {
1241:                        case ParameterMode.IN_INT:
1242:                            // It's hard to validate an arbitrary script expression,
1243:                            // especially at design time when we might not have a
1244:                            // a properly configured WorkFlowEngine and
1245:                            // EvaluatorFactory available.
1246:                            break;
1247:                        case ParameterMode.INOUT_INT:
1248:                        case ParameterMode.OUT_INT:
1249:                            String apName = ap.getText();
1250:                            String prefix = "/ActualParameter[" + fp.getId()
1251:                                    + ']';
1252:                            Object ref = ProcessInstanceAttributes
1253:                                    .findSystemDataField(apName);
1254:                            if (ref == null) {
1255:                                ref = ctx.checkValidIdRef(src, prefix,
1256:                                        XPDLNames.DATA_FIELD,
1257:                                        WORKFLOW_FORMAL_PARAMETER,
1258:                                        PKG_DATA_FIELD, apName);
1259:                            }
1260:                            if (ref == null)
1261:                                break;
1262:                            DataType dt = null;
1263:                            if (ref instanceof  FormalParameter)
1264:                                dt = ((FormalParameter) ref).getDataType();
1265:                            else if (ref instanceof  DataField)
1266:                                dt = ((DataField) ref).getDataType();
1267:                            if (dt == null) {
1268:                                fp.getIndex();
1269:                                ctx.addError(src, DATATYPE_NOT_FOUND,
1270:                                        new Object[] { String.valueOf(i),
1271:                                                apName },
1272:                                        "Unable to determine DataType for ActualParameter["
1273:                                                + i + "]: " + apName);
1274:                            } else {
1275:                                ctx.checkAssignable(src, prefix, fp
1276:                                        .getDataType().getType(), dt.getType());
1277:                            }
1278:                            break;
1279:                        }
1280:                    }
1281:                }
1282:            }
1283:
1284:            private void checkTransitions(Transition[] transitions,
1285:                    ValidationContext ctx) {
1286:
1287:                if (transitions != null) {
1288:                    for (int i = 0, n = transitions.length; i < n; i++)
1289:                        checkTransition(transitions[i], ctx);
1290:                }
1291:            }
1292:
1293:            private void checkTransition(Transition transition,
1294:                    ValidationContext ctx) {
1295:
1296:                String transitionId = transition.getId();
1297:                ctx.pushPrefix("Transition[" + transitionId + ']');
1298:                ctx.checkValidUniqueId(transition, null, XPDLNames.TRANSITION,
1299:                        transitionId, transition);
1300:                if (transition.getFromActivity() == null) {
1301:                    String fromId = transition.getFrom();
1302:                    ctx.addError(transition,
1303:                            TRANSITION_FROM_ACTIVITY_UNDEFINED, new Object[] {
1304:                                    transitionId, fromId },
1305:                            "/From references an undefined Activity[" + fromId
1306:                                    + ']');
1307:                }
1308:                if (transition.getToActivity() == null) {
1309:                    String toId = transition.getTo();
1310:                    ctx.addError(transition, TRANSITION_TO_ACTIVITY_UNDEFINED,
1311:                            new Object[] { transitionId, toId },
1312:                            "/To references an undefined Activity[" + toId
1313:                                    + ']');
1314:                }
1315:                ctx.popPrefix();
1316:            }
1317:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.