View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.orchestra.flow;
20  
21  import javax.faces.application.NavigationHandler;
22  import javax.faces.component.UIViewRoot;
23  import javax.faces.context.FacesContext;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  public class FlowNavigationHandler extends NavigationHandler
29  {
30      private static final Log log = LogFactory.getLog(FlowNavigationHandler.class);
31  
32      private NavigationHandler delegate;
33  
34      /**
35       * Constructor.
36       */
37      public FlowNavigationHandler(NavigationHandler delegate)
38      {
39          this.delegate = delegate;
40      }
41  
42      /**
43       * Ensure that the FlowHandler gets the chance to run after the navigation outcome has been
44       * determined.
45       */
46      @Override
47      public void handleNavigation(FacesContext facesContext, String fromAction, String outcome)
48      {
49          // TODO: what about restoring state that is not in the view tree, eg FacesMessage objects
50          // (which are attached to a FacesContext)? I guess if this is important then it can also
51          // be attached to the FlowInfo object...
52          //
53          // Note that the Tomahawk RedirectTracker is no problem here. It triggers only when a JSF
54          // navigation-rule specifies the <redirect/> tag, and we never expect that to
55          // occur for rules that navigate to the start of a new flow. So RedirectTracker
56          // and Flow effectively have no overlap and will not interfere with each other.
57  
58          UIViewRoot currViewRoot = facesContext.getViewRoot();
59          String oldViewId = currViewRoot.getViewId();
60          log.debug("handleNavigation: view=" + oldViewId + ",outcome=" + outcome);
61  
62          outcome = FlowHandler.processPreNav(facesContext, outcome);
63          
64          if (!facesContext.getResponseComplete())
65          {
66              // Run the normal navigation processing, which will invoke createView on our
67              // custom ViewHandler at which point we know the viewId of the new view and
68              // can complete our processing.
69              //
70              // Alas, JSF doesn't provide an API to just query what outcome a navrule
71              // *would* map to. Note also that if the navigation rule is marked as
72              // <redirect/> then the default handleNavigation does not call createView,
73              // and things screw up badly. That's not a problem though; users simply
74              // must not use redirect on rules navigating to a flow entry.
75              delegate.handleNavigation(facesContext, fromAction, outcome);
76          }
77      }
78  }