You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/06/18 19:24:52 UTC

svn commit: r1494215 - in /myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config: FacesConfigurator.java element/FacesConfigData.java impl/digester/DigesterFacesConfigDispenserImpl.java impl/digester/DigesterFacesConfigUnmarshallerImpl.java

Author: lu4242
Date: Tue Jun 18 17:24:51 2013
New Revision: 1494215

URL: http://svn.apache.org/r1494215
Log:
MYFACES-3691 Implement Faces Flows

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java?rev=1494215&r1=1494214&r2=1494215&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java Tue Jun 18 17:24:51 2013
@@ -59,6 +59,8 @@ import javax.faces.event.PostConstructAp
 import javax.faces.event.PreDestroyCustomScopeEvent;
 import javax.faces.event.PreDestroyViewMapEvent;
 import javax.faces.event.SystemEvent;
+import javax.faces.flow.FlowHandler;
+import javax.faces.flow.FlowHandlerFactory;
 import javax.faces.lifecycle.Lifecycle;
 import javax.faces.lifecycle.LifecycleFactory;
 import javax.faces.render.RenderKit;
@@ -80,8 +82,16 @@ import org.apache.myfaces.config.element
 import org.apache.myfaces.config.element.FaceletsProcessing;
 import org.apache.myfaces.config.element.FacesConfig;
 import org.apache.myfaces.config.element.FacesConfigData;
+import org.apache.myfaces.config.element.FacesFlowCall;
+import org.apache.myfaces.config.element.FacesFlowDefinition;
+import org.apache.myfaces.config.element.FacesFlowMethodCall;
+import org.apache.myfaces.config.element.FacesFlowParameter;
+import org.apache.myfaces.config.element.FacesFlowReturn;
+import org.apache.myfaces.config.element.FacesFlowSwitch;
+import org.apache.myfaces.config.element.FacesFlowView;
 import org.apache.myfaces.config.element.ManagedBean;
 import org.apache.myfaces.config.element.NamedEvent;
+import org.apache.myfaces.config.element.NavigationCase;
 import org.apache.myfaces.config.element.NavigationRule;
 import org.apache.myfaces.config.element.Renderer;
 import org.apache.myfaces.config.element.ResourceBundle;
@@ -97,6 +107,15 @@ import org.apache.myfaces.el.DefaultProp
 import org.apache.myfaces.el.VariableResolverImpl;
 import org.apache.myfaces.el.unified.ResolverBuilderBase;
 import org.apache.myfaces.lifecycle.ClientWindowFactoryImpl;
+import org.apache.myfaces.flow.FlowCallNodeImpl;
+import org.apache.myfaces.flow.FlowHandlerFactoryImpl;
+import org.apache.myfaces.flow.FlowImpl;
+import org.apache.myfaces.flow.MethodCallNodeImpl;
+import org.apache.myfaces.flow.ParameterImpl;
+import org.apache.myfaces.flow.ReturnNodeImpl;
+import org.apache.myfaces.flow.SwitchCaseImpl;
+import org.apache.myfaces.flow.SwitchNodeImpl;
+import org.apache.myfaces.flow.ViewNodeImpl;
 import org.apache.myfaces.lifecycle.LifecycleFactoryImpl;
 import org.apache.myfaces.renderkit.RenderKitFactoryImpl;
 import org.apache.myfaces.renderkit.html.HtmlRenderKitImpl;
@@ -113,7 +132,9 @@ import org.apache.myfaces.spi.ResourceLi
 import org.apache.myfaces.spi.ResourceLibraryContractsProviderFactory;
 import org.apache.myfaces.util.ContainerUtils;
 import org.apache.myfaces.util.ExternalSpecifications;
+import org.apache.myfaces.util.NavigationUtils;
 import org.apache.myfaces.view.ViewDeclarationLanguageFactoryImpl;
+import org.apache.myfaces.view.facelets.el.ELText;
 import org.apache.myfaces.view.facelets.impl.FaceletCacheFactoryImpl;
 import org.apache.myfaces.view.facelets.tag.jsf.TagHandlerDelegateFactoryImpl;
 import org.apache.myfaces.view.facelets.tag.ui.DebugPhaseListener;
@@ -150,6 +171,7 @@ public class FacesConfigurator
     private static final String DEFAULT_FACELET_CACHE_FACTORY = FaceletCacheFactoryImpl.class.getName();
     private static final String DEFAULT_FLASH_FACTORY = ServletFlashFactoryImpl.class.getName();
     private static final String DEFAULT_CLIENT_WINDOW_FACTORY = ClientWindowFactoryImpl.class.getName();
+    private static final String DEFAULT_FLOW_FACTORY = FlowHandlerFactoryImpl.class.getName();
     private static final String DEFAULT_FACES_CONFIG = "/WEB-INF/faces-config.xml";
 
     private final ExternalContext _externalContext;
@@ -438,7 +460,10 @@ public class FacesConfigurator
         configureLifecycle();
         handleSerialFactory();
         configureManagedBeanDestroyer();
+        configureFlowHandler();
 
+        configureProtectedViews();
+        
         // record the time of update
         lastUpdate = System.currentTimeMillis();
     }
@@ -504,6 +529,8 @@ public class FacesConfigurator
                 DEFAULT_FLASH_FACTORY);
         setFactories(FactoryFinder.CLIENT_WINDOW_FACTORY, dispenser.getClientWindowFactoryIterator(),
                 DEFAULT_CLIENT_WINDOW_FACTORY);
+        setFactories(FactoryFinder.FLOW_HANDLER_FACTORY, dispenser.getFlowHandlerFactoryIterator(),
+                DEFAULT_FLOW_FACTORY);
     }
 
     private void setFactories(String factoryName, Collection<String> factories, String defaultFactory)
@@ -687,6 +714,13 @@ public class FacesConfigurator
         {
             application.addBehavior(behavior.getBehaviorId(), behavior.getBehaviorClass());
         }
+        
+        //JSF 2.2 set FlowHandler from factory. 
+        FlowHandlerFactory flowHandlerFactory = (FlowHandlerFactory) 
+            FactoryFinder.getFactory(FactoryFinder.FLOW_HANDLER_FACTORY);
+        FlowHandler flowHandler = flowHandlerFactory.createFlowHandler(
+            FacesContext.getCurrentInstance());
+        application.setFlowHandler(flowHandler);
 
         RuntimeConfig runtimeConfig = getRuntimeConfig();
 
@@ -1148,5 +1182,186 @@ public class FacesConfigurator
                     + "This instance needs to be published before configuration is started.");
         }
     }
+    
+    private void configureFlowHandler()
+    {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        Application application = facesContext.getApplication();
+        
+        FacesConfigData dispenser = getDispenser();
+        
+        for (FacesFlowDefinition flowDefinition : dispenser.getFacesFlowDefinitions())
+        {
+            FlowImpl flow = new FlowImpl();
+            
+            // TODO: configure flow object
+            flow.setId(flowDefinition.getId());
+            flow.setDefiningDocumentId(flowDefinition.getDefiningDocumentId());
+            
+            flow.setStartNodeId(flowDefinition.getStartNode());
+            
+            if (!isEmptyString(flowDefinition.getInitializer()))
+            {
+                flow.setInitializer(application.getExpressionFactory().createMethodExpression(
+                    facesContext.getELContext(), flowDefinition.getInitializer(), null, NO_PARAMETER_TYPES));
+            }
+            if (!isEmptyString(flowDefinition.getFinalizer()))
+            {
+                flow.setFinalizer(application.getExpressionFactory().createMethodExpression(
+                    facesContext.getELContext(), flowDefinition.getFinalizer(), null, NO_PARAMETER_TYPES));
+            }
+            
+            for (FacesFlowCall call : flowDefinition.getFlowCallList())
+            {
+                FlowCallNodeImpl node = new FlowCallNodeImpl(call.getId());
+                node.setCalledFlowId(call.getCalledFlowId());
+
+                for (FacesFlowParameter parameter : call.getOutboundParameterList())
+                {
+                    node.putOutboundParameter( parameter.getName(),
+                        new ParameterImpl(parameter.getName(),
+                        application.getExpressionFactory().createValueExpression(
+                            facesContext.getELContext(), parameter.getValue(), Object.class)) );
+                }
+                flow.putFlowCall(node.getId(), node);
+            }
+
+            for (FacesFlowMethodCall methodCall : flowDefinition.getMethodCallList())
+            {
+                MethodCallNodeImpl node = new MethodCallNodeImpl(methodCall.getId());
+                if (!isEmptyString(methodCall.getMethod()))
+                {
+                    node.setMethodExpression(
+                        application.getExpressionFactory().createMethodExpression(
+                            facesContext.getELContext(), methodCall.getMethod(), null, NO_PARAMETER_TYPES));
+                }
+                if (!isEmptyString(methodCall.getDefaultOutcome()))
+                {
+                    node.setOutcome(
+                        application.getExpressionFactory().createValueExpression(
+                                facesContext.getELContext(), methodCall.getDefaultOutcome(), Object.class));
+                }
+                for (FacesFlowParameter parameter : methodCall.getParameterList())
+                {
+                    node.addParameter(
+                        new ParameterImpl(parameter.getName(),
+                        application.getExpressionFactory().createValueExpression(
+                            facesContext.getELContext(), parameter.getValue(), Object.class)) );
+                }
+                flow.addMethodCall(node);
+            }
+            
+            for (FacesFlowParameter parameter : flowDefinition.getInboundParameterList())
+            {
+                flow.putInboundParameter(parameter.getName(),
+                    new ParameterImpl(parameter.getName(),
+                    application.getExpressionFactory().createValueExpression(
+                        facesContext.getELContext(), parameter.getValue(), Object.class)) );
+            }
+            
+            for (NavigationRule rule : flowDefinition.getNavigationRuleList())
+            {
+                flow.addNavigationCases(rule.getFromViewId(), NavigationUtils.convertNavigationCasesToAPI(rule));
+            }
+            
+            for (FacesFlowSwitch flowSwitch : flowDefinition.getSwitchList())
+            {
+                SwitchNodeImpl node = new SwitchNodeImpl(flowSwitch.getId());
+                
+                if (flowSwitch.getDefaultOutcome() != null &&
+                    !isEmptyString(flowSwitch.getDefaultOutcome().getFromOutcome()))
+                {
+                    if (ELText.isLiteral(flowSwitch.getDefaultOutcome().getFromOutcome()))
+                    {
+                        node.setDefaultOutcome(flowSwitch.getDefaultOutcome().getFromOutcome());
+                    }
+                    else
+                    {
+                        node.setDefaultOutcome(
+                            application.getExpressionFactory().createValueExpression(
+                                facesContext.getELContext(), flowSwitch.getDefaultOutcome().getFromOutcome(),
+                                Object.class));
+                    }
+                }
+                
+                for (NavigationCase navCase : flowSwitch.getNavigationCaseList())
+                {
+                    SwitchCaseImpl nodeCase = new SwitchCaseImpl();
+                    nodeCase.setFromOutcome(navCase.getFromOutcome());
+                    if (!isEmptyString(navCase.getIf()))
+                    {
+                        nodeCase.setCondition(
+                            application.getExpressionFactory().createValueExpression(
+                                facesContext.getELContext(), navCase.getIf(),
+                                Object.class));
+                    }
+                    node.addCase(nodeCase);
+                }
+                
+                flow.putSwitch(node.getId(), node);
+            }
+            
+            for (FacesFlowView view : flowDefinition.getViewList())
+            {
+                ViewNodeImpl node = new ViewNodeImpl(view.getId(), view.getVdlDocument());
+                flow.addView(node);
+            }
+
+            for (FacesFlowReturn flowReturn : flowDefinition.getReturnList())
+            {
+                ReturnNodeImpl node = new ReturnNodeImpl(flowReturn.getId());
+                if (flowReturn.getNavigationCase() != null &&
+                    !isEmptyString(flowReturn.getNavigationCase().getFromOutcome()))
+                {
+                    if (ELText.isLiteral(flowReturn.getNavigationCase().getFromOutcome()))
+                    {
+                        node.setFromOutcome(flowReturn.getNavigationCase().getFromOutcome());
+                    }
+                    else
+                    {
+                        node.setFromOutcome(
+                            application.getExpressionFactory().createValueExpression(
+                                facesContext.getELContext(), flowReturn.getNavigationCase().getFromOutcome(),
+                                Object.class));
+                    }
+                }
+                flow.putReturn(node.getId(), node);
+            }
+            
+            flow.freeze();
+            
+            // Add the flow, so the config can be processed by the flow system and the
+            // navigation system.
+            application.getFlowHandler().addFlow(facesContext, flow);
+        }
+    }
+    
 
+    
+    private boolean isEmptyString(String value)
+    {
+        if (value == null)
+        {
+            return true;
+        }
+        else if (value.length() <= 0)
+        {
+            return true;
+        }
+        return false;
+    }
+
+    public void configureProtectedViews()
+    {
+        Application application = ((ApplicationFactory)
+                FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)).getApplication();
+
+        FacesConfigData dispenser = getDispenser();
+        //Protected Views
+        ViewHandler viewHandler = application.getViewHandler();
+        for (String urlPattern : dispenser.getProtectedViewUrlPatterns())
+        {
+            viewHandler.addProtectedView(urlPattern);
+        }
+    }
 }

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java?rev=1494215&r1=1494214&r2=1494215&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/element/FacesConfigData.java Tue Jun 18 17:24:51 2013
@@ -89,6 +89,15 @@ public abstract class FacesConfigData im
     {
         return Collections.emptyList();
     }
+    
+    /**
+     * @since 2.2
+     * @return 
+     */
+    public Collection<String> getFlowHandlerFactoryIterator()
+    {
+        return Collections.emptyList();
+    }
 
     /** @return Iterator over ActionListener class names (in reverse order!) */
     public abstract Collection<String> getActionListenerIterator();

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java?rev=1494215&r1=1494214&r2=1494215&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigDispenserImpl.java Tue Jun 18 17:24:51 2013
@@ -72,6 +72,7 @@ public class DigesterFacesConfigDispense
     private List<String> faceletCacheFactories = new ArrayList<String>();
     private List<String> flashFactories = new ArrayList<String>();
     private List<String> clientWindowFactories = new ArrayList<String>();
+    private List<String> flowHandlerFactories = new ArrayList<String>();
     
     private String defaultRenderKitId;
     private String messageBundle;
@@ -145,6 +146,7 @@ public class DigesterFacesConfigDispense
             faceletCacheFactories.addAll(factory.getFaceletCacheFactory());
             flashFactories.addAll(factory.getFlashFactory());
             clientWindowFactories.addAll(factory.getClientWindowFactory());
+            flowHandlerFactories.addAll(factory.getFlowHandlerFactory());
         }
 
         components.putAll(config.getComponents());
@@ -729,6 +731,12 @@ public class DigesterFacesConfigDispense
     {
         return flashFactories;
     }
+    
+    @Override
+    public Collection<String> getFlowHandlerFactoryIterator()
+    {
+        return flowHandlerFactories;
+    }
 
     @Override
     public void feedClientWindowFactory(String factoryClassName)

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java?rev=1494215&r1=1494214&r2=1494215&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/impl/digester/DigesterFacesConfigUnmarshallerImpl.java Tue Jun 18 17:24:51 2013
@@ -30,6 +30,7 @@ import javax.faces.context.ExternalConte
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
+import org.apache.myfaces.config.element.FacesFlowDefinition;
 
 /**
  * @author <a href="mailto:oliver@rossmueller.com">Oliver Rossmueller</a>
@@ -141,6 +142,7 @@ public class DigesterFacesConfigUnmarsha
         // 2.2 specific start
         digester.addCallMethod("faces-config/factory/flash-factory", "addFlashFactory", 0);
         // Note there is no client-window-factory, this factory can be set only using SPI.
+        digester.addCallMethod("faces-config/factory/flow-handler-factory", "addFlowHandlerFactory", 0);
         // 2.2 specific end
 
         digester.addObjectCreate("faces-config/factory", Factory.class);
@@ -353,85 +355,80 @@ public class DigesterFacesConfigUnmarsha
     
     private void addFacesFlowRules(ExternalContext externalContext)
     {
-        digester.addObjectCreate("faces-config/faces-flow-definition", FacesFlowDefinitionImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition", "addFacesFlowDefinition");
-        digester.addSetProperties("faces-config/faces-flow-definition", "id", "id");
-        
-        digester.addCallMethod("faces-config/faces-flow-definition/start-node", "setStartNode", 0);
-        digester.addCallMethod("faces-config/faces-flow-definition/initializer", "setInitializer", 0);
-        digester.addCallMethod("faces-config/faces-flow-definition/finalizer", "setFinalizer", 0);
-        
-        digester.addObjectCreate("faces-config/faces-flow-definition/view", FacesFlowViewImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/view", "addView");
-        digester.addSetProperties("faces-config/faces-flow-definition/view", "id", "id");
-        digester.addCallMethod("faces-config/faces-flow-definition/view/vdl-document", "setVdlDocument", 0);
-        
-        digester.addObjectCreate("faces-config/faces-flow-definition/switch", FacesFlowSwitchImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/switch", "addSwitch");
-        digester.addSetProperties("faces-config/faces-flow-definition/switch", "id", "id");
+        digester.addObjectCreate("faces-config/flow-definition", FacesFlowDefinitionImpl.class);
         
-        digester.addObjectCreate("faces-config/faces-flow-definition/switch/default-outcome", 
+        digester.addSetNext("faces-config/flow-definition", "addFacesFlowDefinition");
+        digester.addSetProperties("faces-config/flow-definition", "id", "id");
+        
+        digester.addCallMethod("faces-config/flow-definition/start-node", "setStartNode", 0);
+        digester.addCallMethod("faces-config/flow-definition/initializer", "setInitializer", 0);
+        digester.addCallMethod("faces-config/flow-definition/finalizer", "setFinalizer", 0);
+        
+        digester.addObjectCreate("faces-config/flow-definition/view", FacesFlowViewImpl.class);
+        digester.addSetNext("faces-config/flow-definition/view", "addView");
+        digester.addSetProperties("faces-config/flow-definition/view", "id", "id");
+        digester.addCallMethod("faces-config/flow-definition/view/vdl-document", "setVdlDocument", 0);
+        
+        digester.addObjectCreate("faces-config/flow-definition/switch", FacesFlowSwitchImpl.class);
+        digester.addSetNext("faces-config/flow-definition/switch", "addSwitch");
+        digester.addSetProperties("faces-config/flow-definition/switch", "id", "id");
+        
+        digester.addObjectCreate("faces-config/flow-definition/switch/default-outcome", 
             NavigationCase.class);
-        digester.addSetNext("faces-config/faces-flow-definition/switch/default-outcome", 
+        digester.addSetNext("faces-config/flow-definition/switch/default-outcome", 
             "setDefaultOutcome");
-        digester.addCallMethod("faces-config/faces-flow-definition/switch/default-outcome/from-outcome", 
+        digester.addCallMethod("faces-config/flow-definition/switch/default-outcome/from-outcome", 
             "setFromOutcome", 0);
         
-        addNavigationCases(externalContext, "faces-config/faces-flow-definition/switch/navigation-case",
+        addNavigationCases(externalContext, "faces-config/flow-definition/switch/navigation-case",
             "addNavigationCase");
         
-        digester.addObjectCreate("faces-config/faces-flow-definition/flow-return", FacesFlowReturnImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/flow-return", "addReturn");
-        digester.addSetProperties("faces-config/faces-flow-definition/flow-return", "id", "id");
-        digester.addObjectCreate("faces-config/faces-flow-definition/flow-return/navigation-case", 
+        digester.addObjectCreate("faces-config/flow-definition/flow-return", FacesFlowReturnImpl.class);
+        digester.addSetNext("faces-config/flow-definition/flow-return", "addReturn");
+        digester.addSetProperties("faces-config/flow-definition/flow-return", "id", "id");
+        digester.addObjectCreate("faces-config/flow-definition/flow-return/navigation-case", 
             NavigationCase.class);
-        digester.addSetNext("faces-config/faces-flow-definition/flow-return/navigation-case", 
+        digester.addSetNext("faces-config/flow-definition/flow-return/navigation-case", 
             "setNavigationCase");
-        digester.addCallMethod("faces-config/faces-flow-definition/flow-return/navigation-case/from-outcome", 
+        digester.addCallMethod("faces-config/flow-definition/flow-return/navigation-case/from-outcome", 
             "setFromOutcome", 0);
         
-        addNavigationRules(externalContext, "faces-config/faces-flow-definition/navigation-rule", "addNavigationRule");
+        addNavigationRules(externalContext, "faces-config/flow-definition/navigation-rule", "addNavigationRule");
         
-        digester.addObjectCreate("faces-config/faces-flow-definition/flow-call", FacesFlowCallImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/flow-call", "addFlowCall");
-        digester.addSetProperties("faces-config/faces-flow-definition/flow-call", "id", "id");
+        digester.addObjectCreate("faces-config/flow-definition/flow-call", FacesFlowCallImpl.class);
+        digester.addSetNext("faces-config/flow-definition/flow-call", "addFlowCall");
+        digester.addSetProperties("faces-config/flow-definition/flow-call", "id", "id");
         digester.addCallMethod(
-            "faces-config/faces-flow-definition/flow-call/faces-flow-reference/faces-flow-id", 
+            "faces-config/flow-definition/flow-call/faces-flow-reference/faces-flow-id", 
             "setCalledFlowId", 0);
-        digester.addObjectCreate("faces-config/faces-flow-definition/flow-call/outbound-parameter", 
+        digester.addObjectCreate("faces-config/flow-definition/flow-call/outbound-parameter", 
             FacesFlowParameterImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/flow-call/outbound-parameter", 
+        digester.addSetNext("faces-config/flow-definition/flow-call/outbound-parameter", 
             "addOutboundParameter");
-        digester.addCallMethod("faces-config/faces-flow-definition/flow-call/outbound-parameter/name", "setName", 0);
-        digester.addCallMethod("faces-config/faces-flow-definition/flow-call/outbound-parameter/value", "setValue", 0);
+        digester.addCallMethod("faces-config/flow-definition/flow-call/outbound-parameter/name", "setName", 0);
+        digester.addCallMethod("faces-config/flow-definition/flow-call/outbound-parameter/value", "setValue", 0);
         
-        digester.addObjectCreate("faces-config/faces-flow-definition/method-call", FacesFlowMethodCallImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/method-call", "addMethodCall");
-        digester.addCallMethod("faces-config/faces-flow-definition/method-call/method", "setMethod", 0);
-        digester.addSetProperties("faces-config/faces-flow-definition/method-call/method", "id", "id");
-        digester.addCallMethod("faces-config/faces-flow-definition/method-call/default-outcome", 
+        digester.addObjectCreate("faces-config/flow-definition/method-call", FacesFlowMethodCallImpl.class);
+        digester.addSetNext("faces-config/flow-definition/method-call", "addMethodCall");
+        digester.addCallMethod("faces-config/flow-definition/method-call/method", "setMethod", 0);
+        digester.addSetProperties("faces-config/flow-definition/method-call/method", "id", "id");
+        digester.addCallMethod("faces-config/flow-definition/method-call/default-outcome", 
             "setDefaultOutcome", 0);
-        digester.addObjectCreate("faces-config/faces-flow-definition/method-call/parameter", 
+        digester.addObjectCreate("faces-config/flow-definition/method-call/parameter", 
             FacesFlowMethodParameterImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/method-call/parameter", "addParameter");
-        digester.addCallMethod("faces-config/faces-flow-definition/method-call/parameter/class", "setClassName", 0);
-        digester.addCallMethod("faces-config/faces-flow-definition/method-call/parameter/value", "setValue", 0);
+        digester.addSetNext("faces-config/flow-definition/method-call/parameter", "addParameter");
+        digester.addCallMethod("faces-config/flow-definition/method-call/parameter/class", "setClassName", 0);
+        digester.addCallMethod("faces-config/flow-definition/method-call/parameter/value", "setValue", 0);
         
-        digester.addObjectCreate("faces-config/faces-flow-definition/inbound-parameter", 
+        digester.addObjectCreate("faces-config/flow-definition/inbound-parameter", 
             FacesFlowParameterImpl.class);
-        digester.addSetNext("faces-config/faces-flow-definition/inbound-parameter", "addInboundParameter");
-        digester.addCallMethod("faces-config/faces-flow-definition/inbound-parameter/name", "setName", 0);
-        digester.addCallMethod("faces-config/faces-flow-definition/inbound-parameter/value", "setValue", 0);
+        digester.addSetNext("faces-config/flow-definition/inbound-parameter", "addInboundParameter");
+        digester.addCallMethod("faces-config/flow-definition/inbound-parameter/name", "setName", 0);
+        digester.addCallMethod("faces-config/flow-definition/inbound-parameter/value", "setValue", 0);
     }
 
-    public FacesConfig getFacesConfig(InputStream in, String systemId) throws IOException, SAXException
+    private void postProcessFacesConfig(String systemId, FacesConfig config)
     {
-        InputSource is = new InputSource(in);
-        is.setSystemId(systemId);
-
-        // Fix for http://issues.apache.org/jira/browse/MYFACES-236
-        FacesConfig config = (FacesConfig) digester.parse(is);
-
         for (org.apache.myfaces.config.element.Application application : config.getApplications())
         {
             for (org.apache.myfaces.config.element.LocaleConfig localeConfig : application.getLocaleConfig())
@@ -442,6 +439,37 @@ public class DigesterFacesConfigUnmarsha
                 }
             }
         }
+        
+        for (FacesFlowDefinition facesFlowDefinition : config.getFacesFlowDefinitions())
+        {
+            // JSF 2.2 section 11.4.3.1 says this: "... Flows are defined using the 
+            // <flow-definition> element. This element must have an id attribute which uniquely 
+            // identifies the flow within the scope of the Application Configuration Resource 
+            // file in which the element appears. To enable multiple flows with the same id to 
+            // exist in an application, the <faces-config><name> element is taken to 
+            // be the definingDocumentId of the flow. If no <name> element is specified, 
+            // the empty string is taken as the value for definingDocumentId. ..."
+            if (config.getName() != null)
+            {
+                ((FacesFlowDefinitionImpl)facesFlowDefinition).setDefiningDocumentId(
+                    config.getName());
+            }
+            else
+            {
+                ((FacesFlowDefinitionImpl)facesFlowDefinition).setDefiningDocumentId("");
+            }
+        }
+    }
+    
+    public FacesConfig getFacesConfig(InputStream in, String systemId) throws IOException, SAXException
+    {
+        InputSource is = new InputSource(in);
+        is.setSystemId(systemId);
+
+        // Fix for http://issues.apache.org/jira/browse/MYFACES-236
+        FacesConfig config = (FacesConfig) digester.parse(is);
+
+        postProcessFacesConfig(systemId, config);
 
         return config;
     }
@@ -454,16 +482,7 @@ public class DigesterFacesConfigUnmarsha
         // Fix for http://issues.apache.org/jira/browse/MYFACES-236
         FacesConfig config = (FacesConfig) digester.parse(r);
 
-        for (org.apache.myfaces.config.element.Application application : config.getApplications())
-        {
-            for (org.apache.myfaces.config.element.LocaleConfig localeConfig : application.getLocaleConfig())
-            {
-                if (!localeConfig.getSupportedLocales().contains(localeConfig.getDefaultLocale()))
-                {
-                    localeConfig.getSupportedLocales().add(localeConfig.getDefaultLocale());
-                }
-            }
-        }
+        postProcessFacesConfig(null, config);
 
         return config;
     }