2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.dialog.faces;
19  
20  import javax.faces.application.NavigationHandler;
21  import javax.faces.context.FacesContext;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.shale.dialog.Constants;
26  import org.apache.shale.dialog.DialogContext;
27  import org.apache.shale.dialog.DialogContextManager;
28  import org.apache.shale.dialog.DialogHelper;
29  
30  /***
31   * <p><code>NavigationHandler</code> implementation that allows dialogs to
32   * be created via a logical outcome that returns with a specified prefix.
33   * This is not the only way to start a dialog instance (applications can also
34   * do this programmatically), but it is convenient in many cases.</p>
35   *
36   * @since 1.0.4
37   */
38  public final class DialogNavigationHandler extends NavigationHandler {
39  
40  
41      // ------------------------------------------------------------ Constructors
42  
43  
44      /***
45       * <p>Creates a new instance of DialogNavigationHandler that delegates
46       * to the specified original handler.</p>
47       *
48       * @param original Original NavigationHandler
49       */
50      public DialogNavigationHandler(NavigationHandler original) {
51          if (log.isInfoEnabled()) {
52              log.info("Instantiating DialogNavigationHandler (wrapping instance '"
53                       + original + "')");
54          }
55          this.original = original;
56      }
57  
58  
59      // ------------------------------------------------- DialogContext Variables
60  
61  
62      /***
63       * <p>The <code>Log</code> instance for this class.</p>
64       */
65      private Log log = LogFactory.getLog(DialogNavigationHandler.class);
66  
67  
68      /***
69       * <p>The original <code>NavigationHandler</code> we delegate to.</p>
70       */
71      private NavigationHandler original = null;
72  
73  
74      // ----------------------------------------------- NavigationHandler Methods
75  
76  
77      /***
78       * <p>Handle a navigation request from the application.  The following
79       * rules are applied:</p>
80       * <ul>
81       * <li>If this view is <strong>NOT</strong> currently executing
82       *     a {@link DialogContext} instance:
83       *     <ul>
84       *     <li>If the logical outcome begins with the prefix identified
85       *         by the prefix specified by context init parameter
86       *         <code>Constants.DIALOG_PREFIX_PARAM</code> (with a default
87       *         value of <code>Constants.DIALOG_PREFIX</code>), create and start
88       *         a new {@link DialogContext} instance for a logical name
89       *         based on the remainder of the logical outcome after the
90       *         prefix.</li>
91       *     <li>Otherwise, delegate control to the original navigation
92       *         handler passed to our constructor.</li>
93       *     </ul></li>
94       * <li>If this view is currently executing a {@link DialogContext}
95       *     instance, advance its progress based on the specified logical
96       *     outcome.</li>
97       * </ul>
98       *
99       * @param context FacesContext for the current request
100      * @param fromAction Action that was invoked
101      * @param outcome Logical outcome from the invoked action
102      */
103     public void handleNavigation(FacesContext context, String fromAction,
104                                  String outcome) {
105 
106         if (log.isTraceEnabled()) {
107             log.trace("handleNavigation(context='"
108                       + context + "', fromAction='"
109                       + fromAction + "', outcome='"
110                       + outcome + "')");
111         }
112 
113         DialogContext dcontext = DialogHelper.getDialogContext(context);
114         String prefix = prefix(context);
115         if (dcontext == null) {
116             if ((outcome != null) && outcome.startsWith(prefix)) {
117                 // Create and start a new DialogContext instance
118                 DialogContextManager manager =
119                         DialogHelper.getDialogContextManager(context);
120                 dcontext =
121                   manager.create(context, outcome.substring(prefix.length()));
122                 dcontext.start(context);
123                 if (log.isDebugEnabled()) {
124                     log.debug("Starting dialog '"
125                               + outcome.substring(prefix.length())
126                               + "' for FacesContext instance '"
127                               + context + "' with navigation to viewId '"
128                               + context.getViewRoot().getViewId() + "'");
129                 }
130                 return;
131             } else {
132                 // No active dialog, so delegate to the original handler
133                 original.handleNavigation(context, fromAction, outcome);
134                 return;
135             }
136         } else {
137             // Advance the currently active DialogContext instance
138             dcontext.advance(context, outcome);
139             if (log.isDebugEnabled()) {
140                 log.debug("Advancing dialog '"
141                           + dcontext.getName() + "' for FacesContext '"
142                           + context + "' with navigation to viewId '"
143                           + context.getViewRoot().getViewId() + "'");
144             }
145         }
146 
147     }
148 
149 
150     // --------------------------------------------------------- Private Methods
151 
152 
153     /***
154      * <p>Cache the calculated value of the prefix that triggers starting
155      * a dialog.</p>
156      */
157     private String prefix = null;
158 
159 
160     /***
161      * <p>Return the prefix string that indicates a logical outcome that
162      * should trigger starting a dialog.  The default value can be overridden
163      * by an appropriate context initialization parameter.</p>
164      *
165      * @param context <code>FacesContext</code> for the current request
166      */
167     private String prefix(FacesContext context) {
168 
169         if (prefix != null) {
170             return prefix;
171         }
172         prefix = context.getExternalContext().
173           getInitParameter(Constants.DIALOG_PREFIX_PARAM);
174         if (prefix == null) {
175             prefix = Constants.DIALOG_PREFIX;
176         }
177         return prefix;
178 
179     }
180 
181 
182 }