Source Code Cross Referenced for XmlFlowBuilder.java in  » Workflow-Engines » spring-webflow-1.0.4 » org » springframework » webflow » engine » builder » xml » 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 » spring webflow 1.0.4 » org.springframework.webflow.engine.builder.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2004-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.springframework.webflow.engine.builder.xml;
0017:
0018:        import java.io.IOException;
0019:        import java.util.Arrays;
0020:        import java.util.Collections;
0021:        import java.util.Iterator;
0022:        import java.util.LinkedList;
0023:        import java.util.List;
0024:
0025:        import javax.xml.parsers.ParserConfigurationException;
0026:
0027:        import org.springframework.beans.factory.BeanFactory;
0028:        import org.springframework.beans.factory.config.ConfigurableBeanFactory;
0029:        import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
0030:        import org.springframework.binding.convert.ConversionExecutor;
0031:        import org.springframework.binding.convert.ConversionService;
0032:        import org.springframework.binding.expression.Expression;
0033:        import org.springframework.binding.expression.ExpressionParser;
0034:        import org.springframework.binding.expression.SettableExpression;
0035:        import org.springframework.binding.expression.support.CollectionAddingExpression;
0036:        import org.springframework.binding.mapping.AttributeMapper;
0037:        import org.springframework.binding.mapping.DefaultAttributeMapper;
0038:        import org.springframework.binding.mapping.Mapping;
0039:        import org.springframework.binding.mapping.RequiredMapping;
0040:        import org.springframework.binding.method.MethodSignature;
0041:        import org.springframework.binding.method.Parameter;
0042:        import org.springframework.binding.method.Parameters;
0043:        import org.springframework.context.ApplicationContext;
0044:        import org.springframework.context.support.GenericApplicationContext;
0045:        import org.springframework.core.io.Resource;
0046:        import org.springframework.core.style.ToStringCreator;
0047:        import org.springframework.util.Assert;
0048:        import org.springframework.util.StringUtils;
0049:        import org.springframework.util.xml.DomUtils;
0050:        import org.springframework.web.context.WebApplicationContext;
0051:        import org.springframework.web.context.support.GenericWebApplicationContext;
0052:        import org.springframework.webflow.action.ActionResultExposer;
0053:        import org.springframework.webflow.action.EvaluateAction;
0054:        import org.springframework.webflow.action.SetAction;
0055:        import org.springframework.webflow.core.collection.AttributeMap;
0056:        import org.springframework.webflow.core.collection.LocalAttributeMap;
0057:        import org.springframework.webflow.core.collection.MutableAttributeMap;
0058:        import org.springframework.webflow.engine.AnnotatedAction;
0059:        import org.springframework.webflow.engine.Flow;
0060:        import org.springframework.webflow.engine.FlowAttributeMapper;
0061:        import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
0062:        import org.springframework.webflow.engine.FlowVariable;
0063:        import org.springframework.webflow.engine.TargetStateResolver;
0064:        import org.springframework.webflow.engine.Transition;
0065:        import org.springframework.webflow.engine.TransitionCriteria;
0066:        import org.springframework.webflow.engine.ViewSelector;
0067:        import org.springframework.webflow.engine.builder.BaseFlowBuilder;
0068:        import org.springframework.webflow.engine.builder.FlowArtifactFactory;
0069:        import org.springframework.webflow.engine.builder.FlowBuilderException;
0070:        import org.springframework.webflow.engine.builder.FlowServiceLocator;
0071:        import org.springframework.webflow.engine.support.AttributeExpression;
0072:        import org.springframework.webflow.engine.support.BeanFactoryFlowVariable;
0073:        import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria;
0074:        import org.springframework.webflow.engine.support.SimpleFlowVariable;
0075:        import org.springframework.webflow.engine.support.TransitionCriteriaChain;
0076:        import org.springframework.webflow.engine.support.TransitionExecutingStateExceptionHandler;
0077:        import org.springframework.webflow.execution.Action;
0078:        import org.springframework.webflow.execution.ScopeType;
0079:        import org.springframework.webflow.util.ResourceHolder;
0080:        import org.w3c.dom.Document;
0081:        import org.w3c.dom.Element;
0082:        import org.w3c.dom.Node;
0083:        import org.w3c.dom.NodeList;
0084:        import org.xml.sax.SAXException;
0085:
0086:        /**
0087:         * Flow builder that builds flows as defined in an XML document. The XML document should adhere to the following format:
0088:         *
0089:         * <pre>
0090:         *     &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
0091:         *     &lt;flow xmlns=&quot;http://www.springframework.org/schema/webflow&quot;
0092:         *           xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
0093:         *           xsi:schemaLocation=&quot;http://www.springframework.org/schema/webflow
0094:         *                               http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd&quot;&gt;
0095:         *
0096:         *         &lt;!-- Define your states here --&gt;
0097:         *
0098:         *     &lt;/flow&gt;
0099:         * </pre>
0100:         *
0101:         * <p>
0102:         * Consult the <a href="http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">web flow XML schema</a>
0103:         * for more information on the XML-based flow definition format.
0104:         * <p>
0105:         * This builder will setup a flow-local bean factory for the flow being constructed. That flow-local bean factory will
0106:         * be populated with XML bean definitions contained in files referenced using the "import" element. The flow-local bean
0107:         * factory will use the bean factory defing this flow builder as a parent. As such, the flow can access artifacts in
0108:         * either its flow-local bean factory or in the parent bean factory hierarchy, e.g. the bean factory of the dispatcher.
0109:         *
0110:         * @author Erwin Vervaet
0111:         * @author Keith Donald
0112:         */
0113:        public class XmlFlowBuilder extends BaseFlowBuilder implements 
0114:                ResourceHolder {
0115:
0116:            // recognized XML elements and attributes
0117:
0118:            private static final String ID_ATTRIBUTE = "id";
0119:
0120:            private static final String IDREF_ATTRIBUTE = "idref";
0121:
0122:            private static final String BEAN_ATTRIBUTE = "bean";
0123:
0124:            private static final String FLOW_ELEMENT = "flow";
0125:
0126:            private static final String START_STATE_ELEMENT = "start-state";
0127:
0128:            private static final String ACTION_STATE_ELEMENT = "action-state";
0129:
0130:            private static final String ACTION_ELEMENT = "action";
0131:
0132:            private static final String NAME_ATTRIBUTE = "name";
0133:
0134:            private static final String METHOD_ATTRIBUTE = "method";
0135:
0136:            private static final String BEAN_ACTION_ELEMENT = "bean-action";
0137:
0138:            private static final String METHOD_ARGUMENTS_ELEMENT = "method-arguments";
0139:
0140:            private static final String ARGUMENT_ELEMENT = "argument";
0141:
0142:            private static final String EXPRESSION_ATTRIBUTE = "expression";
0143:
0144:            private static final String PARAMETER_TYPE_ATTRIBUTE = "parameter-type";
0145:
0146:            private static final String METHOD_RESULT_ELEMENT = "method-result";
0147:
0148:            private static final String EVALUATE_ACTION_ELEMENT = "evaluate-action";
0149:
0150:            private static final String SET_ELEMENT = "set";
0151:
0152:            private static final String ATTRIBUTE_ATTRIBUTE = "attribute";
0153:
0154:            private static final String EVALUATION_RESULT_ELEMENT = "evaluation-result";
0155:
0156:            private static final String DEFAULT_VALUE = "default";
0157:
0158:            private static final String VIEW_STATE_ELEMENT = "view-state";
0159:
0160:            private static final String VIEW_ATTRIBUTE = "view";
0161:
0162:            private static final String DECISION_STATE_ELEMENT = "decision-state";
0163:
0164:            private static final String IF_ELEMENT = "if";
0165:
0166:            private static final String TEST_ATTRIBUTE = "test";
0167:
0168:            private static final String THEN_ATTRIBUTE = "then";
0169:
0170:            private static final String ELSE_ATTRIBUTE = "else";
0171:
0172:            private static final String SUBFLOW_STATE_ELEMENT = "subflow-state";
0173:
0174:            private static final String FLOW_ATTRIBUTE = "flow";
0175:
0176:            private static final String ATTRIBUTE_MAPPER_ELEMENT = "attribute-mapper";
0177:
0178:            private static final String OUTPUT_MAPPER_ELEMENT = "output-mapper";
0179:
0180:            private static final String OUTPUT_ATTRIBUTE_ELEMENT = "output-attribute";
0181:
0182:            private static final String INPUT_MAPPER_ELEMENT = "input-mapper";
0183:
0184:            private static final String INPUT_ATTRIBUTE_ELEMENT = "input-attribute";
0185:
0186:            private static final String MAPPING_ELEMENT = "mapping";
0187:
0188:            private static final String SOURCE_ATTRIBUTE = "source";
0189:
0190:            private static final String TARGET_ATTRIBUTE = "target";
0191:
0192:            private static final String FROM_ATTRIBUTE = "from";
0193:
0194:            private static final String TO_ATTRIBUTE = "to";
0195:
0196:            private static final String REQUIRED_ATTRIBUTE = "required";
0197:
0198:            private static final String TARGET_COLLECTION_ATTRIBUTE = "target-collection";
0199:
0200:            private static final String END_STATE_ELEMENT = "end-state";
0201:
0202:            private static final String TRANSITION_ELEMENT = "transition";
0203:
0204:            private static final String GLOBAL_TRANSITIONS_ELEMENT = "global-transitions";
0205:
0206:            private static final String ON_ATTRIBUTE = "on";
0207:
0208:            private static final String ON_EXCEPTION_ATTRIBUTE = "on-exception";
0209:
0210:            private static final String ATTRIBUTE_ELEMENT = "attribute";
0211:
0212:            private static final String TYPE_ATTRIBUTE = "type";
0213:
0214:            private static final String VALUE_ELEMENT = "value";
0215:
0216:            private static final String VALUE_ATTRIBUTE = "value";
0217:
0218:            private static final String VAR_ELEMENT = "var";
0219:
0220:            private static final String SCOPE_ATTRIBUTE = "scope";
0221:
0222:            private static final String CLASS_ATTRIBUTE = "class";
0223:
0224:            private static final String START_ACTIONS_ELEMENT = "start-actions";
0225:
0226:            private static final String END_ACTIONS_ELEMENT = "end-actions";
0227:
0228:            private static final String ENTRY_ACTIONS_ELEMENT = "entry-actions";
0229:
0230:            private static final String RENDER_ACTIONS_ELEMENT = "render-actions";
0231:
0232:            private static final String EXIT_ACTIONS_ELEMENT = "exit-actions";
0233:
0234:            private static final String EXCEPTION_HANDLER_ELEMENT = "exception-handler";
0235:
0236:            private static final String INLINE_FLOW_ELEMENT = "inline-flow";
0237:
0238:            private static final String IMPORT_ELEMENT = "import";
0239:
0240:            private static final String RESOURCE_ATTRIBUTE = "resource";
0241:
0242:            /**
0243:             * The resource from which the document element being parsed was read. Used as a location for relative resource
0244:             * lookup.
0245:             */
0246:            protected Resource location;
0247:
0248:            /**
0249:             * A flow service locator local to this builder that first looks in a locally-managed Spring bean factory for
0250:             * services before searching the externally managed {@link #getFlowServiceLocator() service locator}.
0251:             */
0252:            private LocalFlowServiceLocator localFlowServiceLocator;
0253:
0254:            /**
0255:             * The loader for loading the flow definition resource XML document.
0256:             */
0257:            private DocumentLoader documentLoader = new DefaultDocumentLoader();
0258:
0259:            /**
0260:             * The in-memory document object model (DOM) of the XML Document read from the flow definition resource.
0261:             */
0262:            private Document document;
0263:
0264:            /**
0265:             * Create a new XML flow builder parsing the document at the specified location.
0266:             * @param location the location of the XML-based flow definition resource
0267:             */
0268:            public XmlFlowBuilder(Resource location) {
0269:                setLocation(location);
0270:            }
0271:
0272:            /**
0273:             * Create a new XML flow builder parsing the document at the specified location, using the provided service locator
0274:             * to access externally managed flow artifacts.
0275:             * @param location the location of the XML-based flow definition resource
0276:             * @param flowServiceLocator the locator for services needed by this builder to build its Flow
0277:             */
0278:            public XmlFlowBuilder(Resource location,
0279:                    FlowServiceLocator flowServiceLocator) {
0280:                super (flowServiceLocator);
0281:                setLocation(location);
0282:            }
0283:
0284:            /**
0285:             * Returns the resource from which the document element was loaded. This is used for location relative loading of
0286:             * other resources.
0287:             */
0288:            public Resource getLocation() {
0289:                return location;
0290:            }
0291:
0292:            /**
0293:             * Sets the resource from which the document element was loaded. This is used for location relative loading of other
0294:             * resources.
0295:             */
0296:            public void setLocation(Resource location) {
0297:                Assert
0298:                        .notNull(location,
0299:                                "The resource location of the XML-based flow definition is required");
0300:                this .location = location;
0301:            }
0302:
0303:            /**
0304:             * Sets the loader that will load the XML-based flow definition document. Optional, defaults to
0305:             * {@link DefaultDocumentLoader}.
0306:             * @param documentLoader the document loader
0307:             */
0308:            public void setDocumentLoader(DocumentLoader documentLoader) {
0309:                Assert.notNull(documentLoader,
0310:                        "The XML document loader is required");
0311:                this .documentLoader = documentLoader;
0312:            }
0313:
0314:            public String toString() {
0315:                return new ToStringCreator(this ).append("location", location)
0316:                        .toString();
0317:            }
0318:
0319:            // implementing FlowBuilder
0320:
0321:            public void init(String id, AttributeMap attributes)
0322:                    throws FlowBuilderException {
0323:                localFlowServiceLocator = new LocalFlowServiceLocator(
0324:                        getFlowServiceLocator());
0325:                try {
0326:                    document = documentLoader.loadDocument(location);
0327:                } catch (IOException e) {
0328:                    throw new FlowBuilderException(
0329:                            "Could not access the XML flow definition resource at "
0330:                                    + location, e);
0331:                } catch (ParserConfigurationException e) {
0332:                    throw new FlowBuilderException(
0333:                            "Could not configure the parser to parse the XML flow definition at "
0334:                                    + location, e);
0335:                } catch (SAXException e) {
0336:                    throw new FlowBuilderException(
0337:                            "Could not parse the XML flow definition document at "
0338:                                    + location, e);
0339:                }
0340:                setFlow(parseFlow(id, attributes, getDocumentElement()));
0341:            }
0342:
0343:            public void buildVariables() throws FlowBuilderException {
0344:                parseAndAddFlowVariables(getDocumentElement(), getFlow());
0345:            }
0346:
0347:            public void buildInputMapper() throws FlowBuilderException {
0348:                getFlow()
0349:                        .setInputMapper(parseInputMapper(getDocumentElement()));
0350:            }
0351:
0352:            public void buildStartActions() throws FlowBuilderException {
0353:                parseAndAddStartActions(getDocumentElement(), getFlow());
0354:            }
0355:
0356:            public void buildInlineFlows() throws FlowBuilderException {
0357:                parseAndAddInlineFlowDefinitions(getDocumentElement(),
0358:                        getFlow());
0359:            }
0360:
0361:            public void buildStates() throws FlowBuilderException {
0362:                parseAndAddStateDefinitions(getDocumentElement(), getFlow());
0363:            }
0364:
0365:            public void buildGlobalTransitions() throws FlowBuilderException {
0366:                parseAndAddGlobalTransitions(getDocumentElement(), getFlow());
0367:            }
0368:
0369:            public void buildEndActions() throws FlowBuilderException {
0370:                parseAndAddEndActions(getDocumentElement(), getFlow());
0371:            }
0372:
0373:            public void buildOutputMapper() throws FlowBuilderException {
0374:                getFlow().setOutputMapper(
0375:                        parseOutputMapper(getDocumentElement()));
0376:            }
0377:
0378:            public void buildExceptionHandlers() throws FlowBuilderException {
0379:                getFlow().getExceptionHandlerSet().addAll(
0380:                        parseExceptionHandlers(getDocumentElement()));
0381:            }
0382:
0383:            public void dispose() {
0384:                super .dispose();
0385:                localFlowServiceLocator.diposeOfAnyRegistries();
0386:                document = null;
0387:            }
0388:
0389:            // implementing ResourceHolder
0390:
0391:            public Resource getResource() {
0392:                return location;
0393:            }
0394:
0395:            // helpers
0396:
0397:            /**
0398:             * Returns the DOM document parsed from the XML file.
0399:             */
0400:            protected Document getDocument() {
0401:                return document;
0402:            }
0403:
0404:            /**
0405:             * Returns the root document element.
0406:             */
0407:            protected Element getDocumentElement() {
0408:                return document.getDocumentElement();
0409:            }
0410:
0411:            /**
0412:             * Returns the flow service locator local to this builder.
0413:             */
0414:            protected FlowServiceLocator getLocalFlowServiceLocator() {
0415:                return localFlowServiceLocator;
0416:            }
0417:
0418:            /**
0419:             * Returns the artifact factory of the flow service locator local to this builder.
0420:             */
0421:            protected FlowArtifactFactory getFlowArtifactFactory() {
0422:                return getLocalFlowServiceLocator().getFlowArtifactFactory();
0423:            }
0424:
0425:            // utility (from Spring 2.x DomUtils)
0426:
0427:            /**
0428:             * Utility method that returns the first child element identified by its name.
0429:             * @param ele the DOM element to analyze
0430:             * @param childEleName the child element name to look for
0431:             * @return the <code>org.w3c.dom.Element</code> instance, or <code>null</code> if none found
0432:             */
0433:            protected Element getChildElementByTagName(Element ele,
0434:                    String childEleName) {
0435:                NodeList nl = ele.getChildNodes();
0436:                for (int i = 0; i < nl.getLength(); i++) {
0437:                    Node node = nl.item(i);
0438:                    if (node instanceof  Element
0439:                            && nodeNameEquals(node, childEleName)) {
0440:                        return (Element) node;
0441:                    }
0442:                }
0443:                return null;
0444:            }
0445:
0446:            /**
0447:             * Namespace-aware equals comparison. Returns <code>true</code> if either {@link Node#getLocalName} or
0448:             * {@link Node#getNodeName} equals <code>desiredName</code>, otherwise returns <code>false</code>.
0449:             */
0450:            protected boolean nodeNameEquals(Node node, String desiredName) {
0451:                return desiredName.equals(node.getNodeName())
0452:                        || desiredName.equals(node.getLocalName());
0453:            }
0454:
0455:            // internal parsing logic and hook methods
0456:
0457:            private Flow parseFlow(String id, AttributeMap attributes,
0458:                    Element flowElement) {
0459:                if (!isFlowElement(flowElement)) {
0460:                    throw new IllegalStateException("This is not the '"
0461:                            + FLOW_ELEMENT + "' element");
0462:                }
0463:                Flow flow = getFlowArtifactFactory().createFlow(id,
0464:                        parseAttributes(flowElement).union(attributes));
0465:                initLocalServiceRegistry(flowElement, flow);
0466:                return flow;
0467:            }
0468:
0469:            private boolean isFlowElement(Element flowElement) {
0470:                return nodeNameEquals(flowElement, FLOW_ELEMENT);
0471:            }
0472:
0473:            private void initLocalServiceRegistry(Element flowElement, Flow flow) {
0474:                List importElements = DomUtils.getChildElementsByTagName(
0475:                        flowElement, IMPORT_ELEMENT);
0476:                Resource[] resources = new Resource[importElements.size()];
0477:                for (int i = 0; i < importElements.size(); i++) {
0478:                    Element importElement = (Element) importElements.get(i);
0479:                    try {
0480:                        resources[i] = getLocation().createRelative(
0481:                                importElement.getAttribute(RESOURCE_ATTRIBUTE));
0482:                    } catch (IOException e) {
0483:                        throw new FlowBuilderException(
0484:                                "Could not access flow-relative artifact resource '"
0485:                                        + importElement
0486:                                                .getAttribute(RESOURCE_ATTRIBUTE)
0487:                                        + "'", e);
0488:                    }
0489:                }
0490:                localFlowServiceLocator.push(new LocalFlowServiceRegistry(flow,
0491:                        createLocalBeanFactory(flow, resources)));
0492:            }
0493:
0494:            /**
0495:             * Create a bean factory serving as a local flow service registry.
0496:             * @param flow the current flow definition being built
0497:             * @param resources the file resources to assemble the bean factory from; typically XML-based
0498:             * @return the bean factory
0499:             * @since 1.0.4
0500:             */
0501:            protected BeanFactory createLocalBeanFactory(Flow flow,
0502:                    Resource[] resources) {
0503:                // see if this factory has a parent
0504:                BeanFactory parent = null;
0505:                if (localFlowServiceLocator.isEmpty()) {
0506:                    try {
0507:                        parent = getFlowServiceLocator().getBeanFactory();
0508:                    } catch (UnsupportedOperationException e) {
0509:                        // can't link to a parent
0510:                    }
0511:                } else {
0512:                    parent = localFlowServiceLocator.top().getBeanFactory();
0513:                }
0514:                // determine the context implementation based on the current environment
0515:                GenericApplicationContext context;
0516:                if (parent instanceof  WebApplicationContext) {
0517:                    GenericWebApplicationContext webContext = new GenericWebApplicationContext();
0518:                    webContext
0519:                            .setServletContext(((WebApplicationContext) parent)
0520:                                    .getServletContext());
0521:                    context = webContext;
0522:                } else {
0523:                    context = new GenericApplicationContext();
0524:                }
0525:                // set the parent if necessary
0526:                if (parent instanceof  ApplicationContext) {
0527:                    context.setParent((ApplicationContext) parent);
0528:                } else {
0529:                    if (parent != null) {
0530:                        context.getBeanFactory().setParentBeanFactory(parent);
0531:                    }
0532:                }
0533:                context.setResourceLoader(getFlowServiceLocator()
0534:                        .getResourceLoader());
0535:                new XmlBeanDefinitionReader(context)
0536:                        .loadBeanDefinitions(resources);
0537:                registerLocalBeans(flow, context
0538:                        .getDefaultListableBeanFactory());
0539:                context.refresh();
0540:                return context;
0541:            }
0542:
0543:            /**
0544:             * Register beans in the bean factory local to the flow definition being built.
0545:             * <p>
0546:             * Subclasses may override this metod to customize the population of the bean factory local to
0547:             * the flow definition being built; for example, to register mock implementations of services in a test environment.
0548:             * @param flow the current flow definition being built
0549:             * @param beanFactory the bean factory; register local beans with it using
0550:             * {@link ConfigurableBeanFactory#registerSingleton(String, Object)}
0551:             * @since 1.0.4
0552:             */
0553:            protected void registerLocalBeans(Flow flow,
0554:                    ConfigurableBeanFactory beanFactory) {
0555:            }
0556:
0557:            private void destroyLocalServiceRegistry() {
0558:                localFlowServiceLocator.pop();
0559:            }
0560:
0561:            private void parseAndAddFlowVariables(Element flowElement, Flow flow) {
0562:                List varElements = DomUtils.getChildElementsByTagName(
0563:                        flowElement, VAR_ELEMENT);
0564:                for (Iterator it = varElements.iterator(); it.hasNext();) {
0565:                    flow.addVariable(parseVariable((Element) it.next()));
0566:                }
0567:            }
0568:
0569:            private FlowVariable parseVariable(Element element) {
0570:                ScopeType scope = parseScope(element, ScopeType.FLOW);
0571:                if (StringUtils.hasText(element.getAttribute(BEAN_ATTRIBUTE))) {
0572:                    BeanFactory beanFactory = getLocalFlowServiceLocator()
0573:                            .getBeanFactory();
0574:                    return new BeanFactoryFlowVariable(element
0575:                            .getAttribute(NAME_ATTRIBUTE), element
0576:                            .getAttribute(BEAN_ATTRIBUTE), beanFactory, scope);
0577:                } else {
0578:                    if (StringUtils.hasText(element
0579:                            .getAttribute(CLASS_ATTRIBUTE))) {
0580:                        Class variableClass = (Class) fromStringTo(Class.class)
0581:                                .execute(element.getAttribute(CLASS_ATTRIBUTE));
0582:                        return new SimpleFlowVariable(element
0583:                                .getAttribute(NAME_ATTRIBUTE), variableClass,
0584:                                scope);
0585:                    } else {
0586:                        BeanFactory beanFactory = getLocalFlowServiceLocator()
0587:                                .getBeanFactory();
0588:                        return new BeanFactoryFlowVariable(element
0589:                                .getAttribute(NAME_ATTRIBUTE), null,
0590:                                beanFactory, scope);
0591:                    }
0592:                }
0593:            }
0594:
0595:            private void parseAndAddStartActions(Element element, Flow flow) {
0596:                Element startElement = getChildElementByTagName(element,
0597:                        START_ACTIONS_ELEMENT);
0598:                if (startElement != null) {
0599:                    flow.getStartActionList().addAll(
0600:                            parseAnnotatedActions(startElement));
0601:                }
0602:            }
0603:
0604:            private void parseAndAddEndActions(Element element, Flow flow) {
0605:                Element endElement = getChildElementByTagName(element,
0606:                        END_ACTIONS_ELEMENT);
0607:                if (endElement != null) {
0608:                    flow.getEndActionList().addAll(
0609:                            parseAnnotatedActions(endElement));
0610:                }
0611:            }
0612:
0613:            private void parseAndAddGlobalTransitions(Element element, Flow flow) {
0614:                Element globalTransitionsElement = getChildElementByTagName(
0615:                        element, GLOBAL_TRANSITIONS_ELEMENT);
0616:                if (globalTransitionsElement != null) {
0617:                    flow.getGlobalTransitionSet().addAll(
0618:                            parseTransitions(globalTransitionsElement));
0619:                }
0620:            }
0621:
0622:            private void parseAndAddInlineFlowDefinitions(
0623:                    Element parentFlowElement, Flow flow) {
0624:                List inlineFlowElements = DomUtils.getChildElementsByTagName(
0625:                        parentFlowElement, INLINE_FLOW_ELEMENT);
0626:                for (Iterator it = inlineFlowElements.iterator(); it.hasNext();) {
0627:                    Element inlineFlowElement = (Element) it.next();
0628:                    String inlineFlowId = inlineFlowElement
0629:                            .getAttribute(ID_ATTRIBUTE);
0630:                    Element flowElement = getChildElementByTagName(
0631:                            inlineFlowElement, FLOW_ATTRIBUTE);
0632:                    Flow inlineFlow = parseFlow(inlineFlowId, null, flowElement);
0633:                    buildInlineFlow(flowElement, inlineFlow);
0634:                    flow.addInlineFlow(inlineFlow);
0635:                }
0636:            }
0637:
0638:            private void buildInlineFlow(Element flowElement, Flow inlineFlow) {
0639:                parseAndAddFlowVariables(flowElement, inlineFlow);
0640:                inlineFlow.setInputMapper(parseInputMapper(flowElement));
0641:                parseAndAddStartActions(flowElement, inlineFlow);
0642:                parseAndAddInlineFlowDefinitions(flowElement, inlineFlow);
0643:                parseAndAddStateDefinitions(flowElement, inlineFlow);
0644:                parseAndAddGlobalTransitions(flowElement, inlineFlow);
0645:                parseAndAddEndActions(flowElement, inlineFlow);
0646:                inlineFlow.setOutputMapper(parseOutputMapper(flowElement));
0647:                inlineFlow.getExceptionHandlerSet().addAll(
0648:                        parseExceptionHandlers(flowElement));
0649:
0650:                destroyLocalServiceRegistry();
0651:            }
0652:
0653:            private void parseAndAddStateDefinitions(Element flowElement,
0654:                    Flow flow) {
0655:                NodeList childNodeList = flowElement.getChildNodes();
0656:                for (int i = 0; i < childNodeList.getLength(); i++) {
0657:                    Node childNode = childNodeList.item(i);
0658:                    if (childNode instanceof  Element) {
0659:                        Element stateElement = (Element) childNode;
0660:                        if (nodeNameEquals(stateElement, ACTION_STATE_ELEMENT)) {
0661:                            parseAndAddActionState(stateElement, flow);
0662:                        } else if (nodeNameEquals(stateElement,
0663:                                VIEW_STATE_ELEMENT)) {
0664:                            parseAndAddViewState(stateElement, flow);
0665:                        } else if (nodeNameEquals(stateElement,
0666:                                DECISION_STATE_ELEMENT)) {
0667:                            parseAndAddDecisionState(stateElement, flow);
0668:                        } else if (nodeNameEquals(stateElement,
0669:                                SUBFLOW_STATE_ELEMENT)) {
0670:                            parseAndAddSubflowState(stateElement, flow);
0671:                        } else if (nodeNameEquals(stateElement,
0672:                                END_STATE_ELEMENT)) {
0673:                            parseAndAddEndState(stateElement, flow);
0674:                        }
0675:                    }
0676:                }
0677:                parseAndSetStartState(flowElement, flow);
0678:            }
0679:
0680:            private void parseAndSetStartState(Element element, Flow flow) {
0681:                String startStateId = getStartStateId(element);
0682:                flow.setStartState(startStateId);
0683:            }
0684:
0685:            private String getStartStateId(Element element) {
0686:                Element startStateElement = getChildElementByTagName(element,
0687:                        START_STATE_ELEMENT);
0688:                return startStateElement.getAttribute(IDREF_ATTRIBUTE);
0689:            }
0690:
0691:            private void parseAndAddActionState(Element element, Flow flow) {
0692:                getFlowArtifactFactory().createActionState(parseId(element),
0693:                        flow, parseEntryActions(element),
0694:                        parseAnnotatedActions(element),
0695:                        parseTransitions(element),
0696:                        parseExceptionHandlers(element),
0697:                        parseExitActions(element), parseAttributes(element));
0698:            }
0699:
0700:            private void parseAndAddViewState(Element element, Flow flow) {
0701:                getFlowArtifactFactory().createViewState(parseId(element),
0702:                        flow, parseEntryActions(element),
0703:                        parseViewSelector(element),
0704:                        parseRenderActions(element), parseTransitions(element),
0705:                        parseExceptionHandlers(element),
0706:                        parseExitActions(element), parseAttributes(element));
0707:            }
0708:
0709:            private void parseAndAddDecisionState(Element element, Flow flow) {
0710:                getFlowArtifactFactory().createDecisionState(parseId(element),
0711:                        flow, parseEntryActions(element), parseIfs(element),
0712:                        parseExceptionHandlers(element),
0713:                        parseExitActions(element), parseAttributes(element));
0714:            }
0715:
0716:            private void parseAndAddSubflowState(Element element, Flow flow) {
0717:                getFlowArtifactFactory().createSubflowState(parseId(element),
0718:                        flow, parseEntryActions(element),
0719:                        parseSubflow(element),
0720:                        parseFlowAttributeMapper(element),
0721:                        parseTransitions(element),
0722:                        parseExceptionHandlers(element),
0723:                        parseExitActions(element), parseAttributes(element));
0724:            }
0725:
0726:            private void parseAndAddEndState(Element element, Flow flow) {
0727:                getFlowArtifactFactory().createEndState(parseId(element), flow,
0728:                        parseEntryActions(element), parseViewSelector(element),
0729:                        parseOutputMapper(element),
0730:                        parseExceptionHandlers(element),
0731:                        parseAttributes(element));
0732:            }
0733:
0734:            private String parseId(Element element) {
0735:                return element.getAttribute(ID_ATTRIBUTE);
0736:            }
0737:
0738:            private Action[] parseEntryActions(Element element) {
0739:                Element entryActionsElement = getChildElementByTagName(element,
0740:                        ENTRY_ACTIONS_ELEMENT);
0741:                if (entryActionsElement != null) {
0742:                    return parseAnnotatedActions(entryActionsElement);
0743:                } else {
0744:                    return null;
0745:                }
0746:            }
0747:
0748:            private Action[] parseRenderActions(Element element) {
0749:                Element renderActionsElement = getChildElementByTagName(
0750:                        element, RENDER_ACTIONS_ELEMENT);
0751:                if (renderActionsElement != null) {
0752:                    return parseAnnotatedActions(renderActionsElement);
0753:                } else {
0754:                    return null;
0755:                }
0756:            }
0757:
0758:            private Action[] parseExitActions(Element element) {
0759:                Element exitActionsElement = getChildElementByTagName(element,
0760:                        EXIT_ACTIONS_ELEMENT);
0761:                if (exitActionsElement != null) {
0762:                    return parseAnnotatedActions(exitActionsElement);
0763:                } else {
0764:                    return null;
0765:                }
0766:            }
0767:
0768:            private Transition[] parseTransitions(Element element) {
0769:                List transitions = new LinkedList();
0770:                List transitionElements = DomUtils.getChildElementsByTagName(
0771:                        element, TRANSITION_ELEMENT);
0772:                for (Iterator it = transitionElements.iterator(); it.hasNext();) {
0773:                    Element transitionElement = (Element) it.next();
0774:                    if (!StringUtils.hasText(transitionElement
0775:                            .getAttribute(ON_EXCEPTION_ATTRIBUTE))) {
0776:                        // the "on-exception transition" is not really a transition but rather
0777:                        // a FlowExecutionExceptionHandler (see parseTransitionExecutingExceptionHandlers)
0778:                        transitions.add(parseTransition(transitionElement));
0779:                    }
0780:                }
0781:                return (Transition[]) transitions
0782:                        .toArray(new Transition[transitions.size()]);
0783:            }
0784:
0785:            private Transition parseTransition(Element element) {
0786:                TransitionCriteria matchingCriteria = (TransitionCriteria) fromStringTo(
0787:                        TransitionCriteria.class).execute(
0788:                        element.getAttribute(ON_ATTRIBUTE));
0789:                TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(
0790:                        TargetStateResolver.class).execute(
0791:                        element.getAttribute(TO_ATTRIBUTE));
0792:                TransitionCriteria executionCriteria = TransitionCriteriaChain
0793:                        .criteriaChainFor(parseAnnotatedActions(element));
0794:                return getFlowArtifactFactory().createTransition(
0795:                        targetStateResolver, matchingCriteria,
0796:                        executionCriteria, parseAttributes(element));
0797:            }
0798:
0799:            private ViewSelector parseViewSelector(Element element) {
0800:                String viewName = element.getAttribute(VIEW_ATTRIBUTE);
0801:                return (ViewSelector) fromStringTo(ViewSelector.class).execute(
0802:                        viewName);
0803:            }
0804:
0805:            private Flow parseSubflow(Element element) {
0806:                return getLocalFlowServiceLocator().getSubflow(
0807:                        element.getAttribute(FLOW_ATTRIBUTE));
0808:            }
0809:
0810:            private AnnotatedAction[] parseAnnotatedActions(Element element) {
0811:                List actions = new LinkedList();
0812:                NodeList childNodeList = element.getChildNodes();
0813:                for (int i = 0; i < childNodeList.getLength(); i++) {
0814:                    Node childNode = childNodeList.item(i);
0815:                    if (!(childNode instanceof  Element)) {
0816:                        continue;
0817:                    }
0818:
0819:                    if (nodeNameEquals(childNode, ACTION_ELEMENT)) {
0820:                        // parse standard action
0821:                        actions.add(parseAnnotatedAction((Element) childNode));
0822:                    } else if (nodeNameEquals(childNode, BEAN_ACTION_ELEMENT)) {
0823:                        // parse bean invoking action
0824:                        actions
0825:                                .add(parseAnnotatedBeanInvokingAction((Element) childNode));
0826:                    } else if (nodeNameEquals(childNode,
0827:                            EVALUATE_ACTION_ELEMENT)) {
0828:                        // parse evaluate action
0829:                        actions
0830:                                .add(parseAnnotatedEvaluateAction((Element) childNode));
0831:                    } else if (nodeNameEquals(childNode, SET_ELEMENT)) {
0832:                        // parse set action
0833:                        actions
0834:                                .add(parseAnnotatedSetAction((Element) childNode));
0835:                    }
0836:                }
0837:                return (AnnotatedAction[]) actions
0838:                        .toArray(new AnnotatedAction[actions.size()]);
0839:            }
0840:
0841:            private AnnotatedAction parseAnnotatedAction(Element element) {
0842:                AnnotatedAction annotated = new AnnotatedAction(
0843:                        parseAction(element));
0844:                parseCommonProperties(element, annotated);
0845:                if (element.hasAttribute(METHOD_ATTRIBUTE)) {
0846:                    annotated.setMethod(element.getAttribute(METHOD_ATTRIBUTE));
0847:                }
0848:                return annotated;
0849:            }
0850:
0851:            private Action parseAction(Element element) {
0852:                String actionId = element.getAttribute(BEAN_ATTRIBUTE);
0853:                return getLocalFlowServiceLocator().getAction(actionId);
0854:            }
0855:
0856:            private AnnotatedAction parseCommonProperties(Element element,
0857:                    AnnotatedAction annotated) {
0858:                if (element.hasAttribute(NAME_ATTRIBUTE)) {
0859:                    annotated.setName(element.getAttribute(NAME_ATTRIBUTE));
0860:                }
0861:                annotated.getAttributeMap().putAll(parseAttributes(element));
0862:                return annotated;
0863:            }
0864:
0865:            private AnnotatedAction parseAnnotatedBeanInvokingAction(
0866:                    Element element) {
0867:                AnnotatedAction annotated = new AnnotatedAction(
0868:                        parseBeanInvokingAction(element));
0869:                return parseCommonProperties(element, annotated);
0870:            }
0871:
0872:            private Action parseBeanInvokingAction(Element element) {
0873:                String beanId = element.getAttribute(BEAN_ATTRIBUTE);
0874:                String methodName = element.getAttribute(METHOD_ATTRIBUTE);
0875:                Parameters parameters = parseMethodParameters(element);
0876:                MethodSignature methodSignature = new MethodSignature(
0877:                        methodName, parameters);
0878:                ActionResultExposer resultExposer = parseMethodResultExposer(element);
0879:                return getLocalFlowServiceLocator()
0880:                        .getBeanInvokingActionFactory()
0881:                        .createBeanInvokingAction(
0882:                                beanId,
0883:                                getLocalFlowServiceLocator().getBeanFactory(),
0884:                                methodSignature,
0885:                                resultExposer,
0886:                                getLocalFlowServiceLocator()
0887:                                        .getConversionService(), null);
0888:            }
0889:
0890:            private Parameters parseMethodParameters(Element element) {
0891:                Element methodArgumentsElement = getChildElementByTagName(
0892:                        element, METHOD_ARGUMENTS_ELEMENT);
0893:                if (methodArgumentsElement == null) {
0894:                    return Parameters.NONE;
0895:                }
0896:                Parameters parameters = new Parameters();
0897:                Iterator it = DomUtils.getChildElementsByTagName(
0898:                        methodArgumentsElement, ARGUMENT_ELEMENT).iterator();
0899:                while (it.hasNext()) {
0900:                    Element argumentElement = (Element) it.next();
0901:                    Expression name = getLocalFlowServiceLocator()
0902:                            .getExpressionParser()
0903:                            .parseExpression(
0904:                                    argumentElement
0905:                                            .getAttribute(EXPRESSION_ATTRIBUTE));
0906:                    Class type = null;
0907:                    if (argumentElement.hasAttribute(PARAMETER_TYPE_ATTRIBUTE)) {
0908:                        type = (Class) fromStringTo(Class.class)
0909:                                .execute(
0910:                                        argumentElement
0911:                                                .getAttribute(PARAMETER_TYPE_ATTRIBUTE));
0912:                    }
0913:                    parameters.add(new Parameter(type, name));
0914:                }
0915:                return parameters;
0916:            }
0917:
0918:            private ActionResultExposer parseMethodResultExposer(Element element) {
0919:                Element resultElement = getChildElementByTagName(element,
0920:                        METHOD_RESULT_ELEMENT);
0921:                if (resultElement != null) {
0922:                    return parseActionResultExposer(resultElement);
0923:                } else {
0924:                    return null;
0925:                }
0926:            }
0927:
0928:            private ActionResultExposer parseActionResultExposer(Element element) {
0929:                String resultName = element.getAttribute(NAME_ATTRIBUTE);
0930:                return new ActionResultExposer(resultName, parseScope(element,
0931:                        ScopeType.REQUEST));
0932:            }
0933:
0934:            private AnnotatedAction parseAnnotatedEvaluateAction(Element element) {
0935:                AnnotatedAction annotated = new AnnotatedAction(
0936:                        parseEvaluateAction(element));
0937:                return parseCommonProperties(element, annotated);
0938:            }
0939:
0940:            private Action parseEvaluateAction(Element element) {
0941:                String expressionString = element
0942:                        .getAttribute(EXPRESSION_ATTRIBUTE);
0943:                Expression expression = getLocalFlowServiceLocator()
0944:                        .getExpressionParser()
0945:                        .parseExpression(expressionString);
0946:                return new EvaluateAction(expression,
0947:                        parseEvaluationResultExposer(element));
0948:            }
0949:
0950:            private ActionResultExposer parseEvaluationResultExposer(
0951:                    Element element) {
0952:                Element resultElement = getChildElementByTagName(element,
0953:                        EVALUATION_RESULT_ELEMENT);
0954:                if (resultElement != null) {
0955:                    return parseActionResultExposer(resultElement);
0956:                } else {
0957:                    return null;
0958:                }
0959:            }
0960:
0961:            private AnnotatedAction parseAnnotatedSetAction(Element element) {
0962:                AnnotatedAction annotated = new AnnotatedAction(
0963:                        parseSetAction(element));
0964:                return parseCommonProperties(element, annotated);
0965:            }
0966:
0967:            private Action parseSetAction(Element element) {
0968:                String attributeExpressionString = element
0969:                        .getAttribute(ATTRIBUTE_ATTRIBUTE);
0970:                SettableExpression attributeExpression = getLocalFlowServiceLocator()
0971:                        .getExpressionParser().parseSettableExpression(
0972:                                attributeExpressionString);
0973:                Expression valueExpression = getLocalFlowServiceLocator()
0974:                        .getExpressionParser().parseExpression(
0975:                                element.getAttribute(VALUE_ATTRIBUTE));
0976:                return new SetAction(attributeExpression, parseScope(element,
0977:                        ScopeType.REQUEST), valueExpression);
0978:            }
0979:
0980:            private ScopeType parseScope(Element element, ScopeType defaultValue) {
0981:                if (element.hasAttribute(SCOPE_ATTRIBUTE)
0982:                        && !element.getAttribute(SCOPE_ATTRIBUTE).equals(
0983:                                DEFAULT_VALUE)) {
0984:                    return (ScopeType) fromStringTo(ScopeType.class).execute(
0985:                            element.getAttribute(SCOPE_ATTRIBUTE));
0986:                } else {
0987:                    return defaultValue;
0988:                }
0989:            }
0990:
0991:            private AttributeMap parseAttributes(Element element) {
0992:                LocalAttributeMap attributes = new LocalAttributeMap();
0993:                List propertyElements = DomUtils.getChildElementsByTagName(
0994:                        element, ATTRIBUTE_ELEMENT);
0995:                for (int i = 0; i < propertyElements.size(); i++) {
0996:                    parseAndSetAttribute((Element) propertyElements.get(i),
0997:                            attributes);
0998:                }
0999:                return attributes;
1000:            }
1001:
1002:            private void parseAndSetAttribute(Element element,
1003:                    MutableAttributeMap attributes) {
1004:                String name = element.getAttribute(NAME_ATTRIBUTE);
1005:                String value = null;
1006:                if (element.hasAttribute(VALUE_ATTRIBUTE)) {
1007:                    value = element.getAttribute(VALUE_ATTRIBUTE);
1008:                } else {
1009:                    List valueElements = DomUtils.getChildElementsByTagName(
1010:                            element, VALUE_ELEMENT);
1011:                    Assert.state(valueElements.size() == 1,
1012:                            "A property value should be specified for property '"
1013:                                    + name + "'");
1014:                    value = DomUtils.getTextValue((Element) valueElements
1015:                            .get(0));
1016:                }
1017:                attributes.put(name, convertPropertyValue(element, value));
1018:            }
1019:
1020:            private Object convertPropertyValue(Element element,
1021:                    String stringValue) {
1022:                if (element.hasAttribute(TYPE_ATTRIBUTE)) {
1023:                    Class targetClass = (Class) fromStringTo(Class.class)
1024:                            .execute(element.getAttribute(TYPE_ATTRIBUTE));
1025:                    // convert string value to instance of target class
1026:                    return fromStringTo(targetClass).execute(stringValue);
1027:                } else {
1028:                    return stringValue;
1029:                }
1030:            }
1031:
1032:            private Transition[] parseIfs(Element element) {
1033:                List transitions = new LinkedList();
1034:                List transitionElements = DomUtils.getChildElementsByTagName(
1035:                        element, IF_ELEMENT);
1036:                for (Iterator it = transitionElements.iterator(); it.hasNext();) {
1037:                    transitions.addAll(Arrays.asList(parseIf((Element) it
1038:                            .next())));
1039:                }
1040:                return (Transition[]) transitions
1041:                        .toArray(new Transition[transitions.size()]);
1042:            }
1043:
1044:            private Transition[] parseIf(Element element) {
1045:                Transition thenTransition = parseThen(element);
1046:                if (StringUtils.hasText(element.getAttribute(ELSE_ATTRIBUTE))) {
1047:                    Transition elseTransition = parseElse(element);
1048:                    return new Transition[] { thenTransition, elseTransition };
1049:                } else {
1050:                    return new Transition[] { thenTransition };
1051:                }
1052:            }
1053:
1054:            private Transition parseThen(Element element) {
1055:                Expression expression = getLocalFlowServiceLocator()
1056:                        .getExpressionParser().parseExpression(
1057:                                element.getAttribute(TEST_ATTRIBUTE));
1058:                TransitionCriteria matchingCriteria = new BooleanExpressionTransitionCriteria(
1059:                        expression);
1060:                TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(
1061:                        TargetStateResolver.class).execute(
1062:                        element.getAttribute(THEN_ATTRIBUTE));
1063:                return getFlowArtifactFactory().createTransition(
1064:                        targetStateResolver, matchingCriteria, null, null);
1065:            }
1066:
1067:            private Transition parseElse(Element element) {
1068:                TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(
1069:                        TargetStateResolver.class).execute(
1070:                        element.getAttribute(ELSE_ATTRIBUTE));
1071:                return getFlowArtifactFactory().createTransition(
1072:                        targetStateResolver, null, null, null);
1073:            }
1074:
1075:            private FlowAttributeMapper parseFlowAttributeMapper(Element element) {
1076:                Element mapperElement = getChildElementByTagName(element,
1077:                        ATTRIBUTE_MAPPER_ELEMENT);
1078:                if (mapperElement == null) {
1079:                    return null;
1080:                }
1081:                if (StringUtils.hasText(mapperElement
1082:                        .getAttribute(BEAN_ATTRIBUTE))) {
1083:                    return getLocalFlowServiceLocator().getAttributeMapper(
1084:                            mapperElement.getAttribute(BEAN_ATTRIBUTE));
1085:                } else {
1086:                    return new ImmutableFlowAttributeMapper(
1087:                            parseInputMapper(mapperElement),
1088:                            parseOutputMapper(mapperElement));
1089:                }
1090:            }
1091:
1092:            private AttributeMapper parseInputMapper(Element element) {
1093:                Element mapperElement = getChildElementByTagName(element,
1094:                        INPUT_MAPPER_ELEMENT);
1095:                if (mapperElement != null) {
1096:                    DefaultAttributeMapper mapper = new DefaultAttributeMapper();
1097:                    parseSimpleAttributeMappings(mapper, DomUtils
1098:                            .getChildElementsByTagName(mapperElement,
1099:                                    INPUT_ATTRIBUTE_ELEMENT));
1100:                    parseMappings(mapper, mapperElement);
1101:                    return mapper;
1102:                } else {
1103:                    return null;
1104:                }
1105:            }
1106:
1107:            private AttributeMapper parseOutputMapper(Element element) {
1108:                Element mapperElement = getChildElementByTagName(element,
1109:                        OUTPUT_MAPPER_ELEMENT);
1110:                if (mapperElement != null) {
1111:                    DefaultAttributeMapper mapper = new DefaultAttributeMapper();
1112:                    parseSimpleAttributeMappings(mapper, DomUtils
1113:                            .getChildElementsByTagName(mapperElement,
1114:                                    OUTPUT_ATTRIBUTE_ELEMENT));
1115:                    parseMappings(mapper, mapperElement);
1116:                    return mapper;
1117:                } else {
1118:                    return null;
1119:                }
1120:            }
1121:
1122:            private void parseMappings(DefaultAttributeMapper mapper,
1123:                    Element element) {
1124:                ExpressionParser parser = getLocalFlowServiceLocator()
1125:                        .getExpressionParser();
1126:                List mappingElements = DomUtils.getChildElementsByTagName(
1127:                        element, MAPPING_ELEMENT);
1128:                for (Iterator it = mappingElements.iterator(); it.hasNext();) {
1129:                    Element mappingElement = (Element) it.next();
1130:                    Expression source = parser.parseExpression(mappingElement
1131:                            .getAttribute(SOURCE_ATTRIBUTE));
1132:                    SettableExpression target = null;
1133:                    if (StringUtils.hasText(mappingElement
1134:                            .getAttribute(TARGET_ATTRIBUTE))) {
1135:                        target = parser.parseSettableExpression(mappingElement
1136:                                .getAttribute(TARGET_ATTRIBUTE));
1137:                    } else if (StringUtils.hasText(mappingElement
1138:                            .getAttribute(TARGET_COLLECTION_ATTRIBUTE))) {
1139:                        target = new CollectionAddingExpression(
1140:                                parser
1141:                                        .parseSettableExpression(mappingElement
1142:                                                .getAttribute(TARGET_COLLECTION_ATTRIBUTE)));
1143:                    }
1144:                    if (getRequired(mappingElement, false)) {
1145:                        mapper.addMapping(new RequiredMapping(source, target,
1146:                                parseTypeConverter(mappingElement)));
1147:                    } else {
1148:                        mapper.addMapping(new Mapping(source, target,
1149:                                parseTypeConverter(mappingElement)));
1150:                    }
1151:                }
1152:            }
1153:
1154:            private void parseSimpleAttributeMappings(
1155:                    DefaultAttributeMapper mapper, List elements) {
1156:                ExpressionParser parser = getLocalFlowServiceLocator()
1157:                        .getExpressionParser();
1158:                for (Iterator it = elements.iterator(); it.hasNext();) {
1159:                    Element element = (Element) it.next();
1160:                    SettableExpression attribute = parser
1161:                            .parseSettableExpression(element
1162:                                    .getAttribute(NAME_ATTRIBUTE));
1163:                    SettableExpression expression = new AttributeExpression(
1164:                            attribute, parseScope(element, ScopeType.FLOW));
1165:                    if (getRequired(element, false)) {
1166:                        mapper.addMapping(new RequiredMapping(expression,
1167:                                expression, null));
1168:                    } else {
1169:                        mapper.addMapping(new Mapping(expression, expression,
1170:                                null));
1171:                    }
1172:                }
1173:            }
1174:
1175:            private boolean getRequired(Element element, boolean defaultValue) {
1176:                if (StringUtils.hasText(element
1177:                        .getAttribute(REQUIRED_ATTRIBUTE))) {
1178:                    return ((Boolean) fromStringTo(Boolean.class).execute(
1179:                            element.getAttribute(REQUIRED_ATTRIBUTE)))
1180:                            .booleanValue();
1181:                } else {
1182:                    return defaultValue;
1183:                }
1184:            }
1185:
1186:            private ConversionExecutor parseTypeConverter(Element element) {
1187:                String from = element.getAttribute(FROM_ATTRIBUTE);
1188:                String to = element.getAttribute(TO_ATTRIBUTE);
1189:                if (StringUtils.hasText(from)) {
1190:                    if (StringUtils.hasText(to)) {
1191:                        ConversionService service = getLocalFlowServiceLocator()
1192:                                .getConversionService();
1193:                        Class sourceClass = (Class) fromStringTo(Class.class)
1194:                                .execute(from);
1195:                        Class targetClass = (Class) fromStringTo(Class.class)
1196:                                .execute(to);
1197:                        return service.getConversionExecutor(sourceClass,
1198:                                targetClass);
1199:                    } else {
1200:                        throw new IllegalArgumentException(
1201:                                "Use of the 'from' attribute requires use of the 'to' attribute");
1202:                    }
1203:                } else {
1204:                    Assert
1205:                            .isTrue(!StringUtils.hasText(to),
1206:                                    "Use of the 'to' attribute requires use of the 'from' attribute");
1207:                }
1208:                return null;
1209:            }
1210:
1211:            private FlowExecutionExceptionHandler[] parseExceptionHandlers(
1212:                    Element element) {
1213:                FlowExecutionExceptionHandler[] transitionExecutingHandlers = parseTransitionExecutingExceptionHandlers(element);
1214:                FlowExecutionExceptionHandler[] customHandlers = parseCustomExceptionHandlers(element);
1215:                FlowExecutionExceptionHandler[] exceptionHandlers = new FlowExecutionExceptionHandler[transitionExecutingHandlers.length
1216:                        + customHandlers.length];
1217:                System.arraycopy(transitionExecutingHandlers, 0,
1218:                        exceptionHandlers, 0,
1219:                        transitionExecutingHandlers.length);
1220:                System.arraycopy(customHandlers, 0, exceptionHandlers,
1221:                        transitionExecutingHandlers.length,
1222:                        customHandlers.length);
1223:                return exceptionHandlers;
1224:            }
1225:
1226:            private FlowExecutionExceptionHandler[] parseTransitionExecutingExceptionHandlers(
1227:                    Element element) {
1228:                List transitionElements = Collections.EMPTY_LIST;
1229:                if (isFlowElement(element)) {
1230:                    Element globalTransitionsElement = getChildElementByTagName(
1231:                            element, GLOBAL_TRANSITIONS_ELEMENT);
1232:                    if (globalTransitionsElement != null) {
1233:                        transitionElements = DomUtils
1234:                                .getChildElementsByTagName(
1235:                                        globalTransitionsElement,
1236:                                        TRANSITION_ELEMENT);
1237:                    }
1238:                } else {
1239:                    transitionElements = DomUtils.getChildElementsByTagName(
1240:                            element, TRANSITION_ELEMENT);
1241:                }
1242:                List exceptionHandlers = new LinkedList();
1243:                for (Iterator it = transitionElements.iterator(); it.hasNext();) {
1244:                    Element transitionElement = (Element) it.next();
1245:                    if (StringUtils.hasText(transitionElement
1246:                            .getAttribute(ON_EXCEPTION_ATTRIBUTE))) {
1247:                        // the "on-exception transitions" are not really transitions but rather
1248:                        // FlowExecutionExceptionHandlers
1249:                        exceptionHandlers
1250:                                .add(parseTransitionExecutingExceptionHandler(transitionElement));
1251:                    }
1252:                }
1253:                return (FlowExecutionExceptionHandler[]) exceptionHandlers
1254:                        .toArray(new FlowExecutionExceptionHandler[exceptionHandlers
1255:                                .size()]);
1256:            }
1257:
1258:            private FlowExecutionExceptionHandler parseTransitionExecutingExceptionHandler(
1259:                    Element element) {
1260:                TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler();
1261:                Class exceptionClass = (Class) fromStringTo(Class.class)
1262:                        .execute(element.getAttribute(ON_EXCEPTION_ATTRIBUTE));
1263:                TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(
1264:                        TargetStateResolver.class).execute(
1265:                        element.getAttribute(TO_ATTRIBUTE));
1266:                handler.add(exceptionClass, targetStateResolver);
1267:                handler.getActionList().addAll(parseAnnotatedActions(element));
1268:                return handler;
1269:            }
1270:
1271:            private FlowExecutionExceptionHandler[] parseCustomExceptionHandlers(
1272:                    Element element) {
1273:                List exceptionHandlers = new LinkedList();
1274:                List handlerElements = DomUtils.getChildElementsByTagName(
1275:                        element, EXCEPTION_HANDLER_ELEMENT);
1276:                for (int i = 0; i < handlerElements.size(); i++) {
1277:                    Element handlerElement = (Element) handlerElements.get(i);
1278:                    exceptionHandlers
1279:                            .add(parseCustomExceptionHandler(handlerElement));
1280:                }
1281:                return (FlowExecutionExceptionHandler[]) exceptionHandlers
1282:                        .toArray(new FlowExecutionExceptionHandler[exceptionHandlers
1283:                                .size()]);
1284:            }
1285:
1286:            private FlowExecutionExceptionHandler parseCustomExceptionHandler(
1287:                    Element element) {
1288:                return getLocalFlowServiceLocator().getExceptionHandler(
1289:                        element.getAttribute(BEAN_ATTRIBUTE));
1290:            }
1291:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.