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.ViewHandler;
22  import javax.faces.application.ViewHandlerWrapper;
23  import javax.faces.component.UIViewRoot;
24  import javax.faces.context.FacesContext;
25  
26  /**
27   * Custom ViewHandler that executes the necessary logic to handle entering and exiting a Flow.
28   * <p>
29   * Combining this class with other ViewHandlers can cause unexpected results, particularly when
30   * libararies in the classpath include faces-config.xml files that automatically register custom
31   * ViewHandler classes as in that case the order of ViewHandler nesting is hard to control. The most
32   * significant library that registers a custom ViewHandler is Facelets, but that is not a problem: this
33   * class only actually cares about the createView method, and Facelets does not do anything significant
34   * in its createView implementation.
35   */
36  public class FlowViewHandler extends ViewHandlerWrapper
37  {
38      private ViewHandler delegate;
39  
40      /**
41       * Constructor.
42       */
43      public FlowViewHandler(ViewHandler delegate)
44      {
45          this.delegate = delegate;
46      }
47  
48      @Override
49      protected ViewHandler getWrapped()
50      {
51          return delegate;
52      }
53  
54      /**
55       * Special createView handling for Orchestra Flows.
56       * <p>
57       * When this request was a postback that started a flowcall:
58       * <ul>
59       * <li>validate that this new view is a suitable flow entry point
60       * <li>import passed parameters into child context
61       * <li>for non-modal call: send a redirect to this view
62       * <li>for modal call: rerender the *old* view, which should then
63       * trigger a GET to the new view in a new window or frame.
64       * </ul>
65       * <p>
66       * When this request was a postback that started a flowreturn:
67       * <ul>
68       * <li>Normally the view to return to is known so this code is not executed.
69       * <li>When the view to return to has a "return handler" that provides 
70       * a nav-outcome then this code is executed; just redirect to the desired view.
71       * </ul>
72       * <p>
73       * Throws OrchestraException if there is a flow error, eg if the view
74       * specified is the entry point for a flow but the previous view did
75       * not do a FlowCall.
76       */
77      public UIViewRoot createView(FacesContext facesContext, String newViewId)
78      {
79          UIViewRoot viewRoot = FlowHandler.processPreCreateView(facesContext, delegate, newViewId);
80          if (viewRoot == null)
81          {
82              if (facesContext.getResponseComplete())
83              {
84                  // We will never use the viewRoot returned from this method because the response
85                  // is already complete. However this method is not allowed to return null, so
86                  // here we return a dummy root object.
87                 viewRoot = new UIViewRoot();
88              }
89              else
90              {
91                  viewRoot = delegate.createView(facesContext, newViewId);    
92              }
93          }
94          return viewRoot;
95      }
96  }