KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > app > AlfrescoNavigationHandler


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the GNU Lesser General Public License as
5  * published by the Free Software Foundation; either version
6  * 2.1 of the License, or (at your option) any later version.
7  * You may obtain a copy of the License at
8  *
9  * http://www.gnu.org/licenses/lgpl.txt
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14  * either express or implied. See the License for the specific
15  * language governing permissions and limitations under the
16  * License.
17  */

18 package org.alfresco.web.app;
19
20 import java.util.Stack JavaDoc;
21
22 import javax.faces.application.NavigationHandler;
23 import javax.faces.application.ViewHandler;
24 import javax.faces.component.UIViewRoot;
25 import javax.faces.context.FacesContext;
26
27 import org.alfresco.config.Config;
28 import org.alfresco.config.ConfigService;
29 import org.alfresco.web.bean.NavigationBean;
30 import org.alfresco.web.bean.repository.Node;
31 import org.alfresco.web.config.NavigationConfigElement;
32 import org.alfresco.web.config.NavigationElementReader;
33 import org.alfresco.web.config.NavigationResult;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.springframework.web.jsf.FacesContextUtils;
37
38 /**
39  * @author gavinc
40  */

41 public class AlfrescoNavigationHandler extends NavigationHandler
42 {
43    public final static String JavaDoc DIALOG_SEPARATOR = ":";
44    public final static String JavaDoc DIALOG_PREXIX = "dialog" + DIALOG_SEPARATOR;
45    public final static String JavaDoc CLOSE_DIALOG_OUTCOME = DIALOG_PREXIX + "close";
46    
47    private final static Log logger = LogFactory.getLog(AlfrescoNavigationHandler.class);
48    private final static String JavaDoc VIEW_STACK = "_alfViewStack";
49    
50    // The original navigation handler
51
private NavigationHandler origHandler;
52    
53    /**
54     * Default constructor
55     *
56     * @param origHandler The original navigation handler
57     */

58    public AlfrescoNavigationHandler(NavigationHandler origHandler)
59    {
60       super();
61       this.origHandler = origHandler;
62    }
63
64    /**
65     * @see javax.faces.application.NavigationHandler#handleNavigation(javax.faces.context.FacesContext, java.lang.String, java.lang.String)
66     */

67    @Override JavaDoc
68    @SuppressWarnings JavaDoc("unchecked")
69    public void handleNavigation(FacesContext context, String JavaDoc fromAction, String JavaDoc outcome)
70    {
71       if (logger.isDebugEnabled())
72          logger.debug("handleNavigation (fromAction=" + fromAction + ", outcome=" + outcome + ")");
73       
74       boolean useOriginalNavHandler = true;
75       boolean closingDialog = false;
76       String JavaDoc viewId = context.getViewRoot().getViewId();
77       
78       if (logger.isDebugEnabled())
79          logger.debug("Current view id: " + viewId);
80       
81       // determine if we are dealing with a dialog
82
if (outcome != null && outcome.startsWith(DIALOG_PREXIX))
83       {
84          // determine whether it's being closed or opened
85
closingDialog = outcome.startsWith(CLOSE_DIALOG_OUTCOME);
86          
87          // remove the dialog prefix
88
outcome = outcome.substring(DIALOG_PREXIX.length());
89
90          if (closingDialog)
91          {
92             // if we are closing the dialog take the view off the
93
// top of the stack then decide whether to use the view
94
// or any overridden outcome that may be present
95
if (getViewStack(context).empty() == false)
96             {
97                String JavaDoc newViewId = (String JavaDoc)getViewStack(context).pop();
98             
99                // is there an overiddent outcome?
100
int idx = outcome.indexOf(DIALOG_SEPARATOR);
101                if (idx == -1)
102                {
103                   // there isn't an overidden outcome so go back to the previous view
104
if (logger.isDebugEnabled())
105                      logger.debug("Closing dialog, going back to view id: " + newViewId);
106                
107                   goToView(context, newViewId);
108                }
109                else
110                {
111                   // there is an overidden outcome so extract it
112
outcome = outcome.substring(idx+1, outcome.length());
113                   
114                   // we also need to empty the dialog stack if we have been given
115
// an overidden outcome as we could be going anywhere in the app
116
getViewStack(context).clear();
117                   
118                   if (logger.isDebugEnabled())
119                      logger.debug("Closing dialog with an overridden outcome of '" + outcome + "'");
120                   
121                   this.origHandler.handleNavigation(context, fromAction, outcome);
122                }
123             }
124             else
125             {
126                // we are trying to close a dialog when one hasn't been opened!
127
// log a warning and return a null outcome to stay on the same page
128
if (logger.isWarnEnabled())
129                {
130                   logger.warn("Attempting to close a dialog with an empty view stack, returning null outcome");
131                }
132                
133                this.origHandler.handleNavigation(context, fromAction, null);
134             }
135          }
136          else
137          {
138             // if we are opening a dialog push the current view id
139
// on to the stack, but only if it is different than the
140
// current view at the top (you can't launch a dialog from
141
// the same page 2 times in a row!)
142

143             // TODO: This wouldn't happen if we could be sure a dialog is
144
// ALWAYS exited properly, look into a way of ensuring
145
// dialogs get closed if a user navigates away from the page,
146
// would a PhaseListener help in any way??
147

148             if (getViewStack(context).empty() ||
149                 viewId.equals(getViewStack(context).peek()) == false)
150             {
151                getViewStack(context).push(viewId);
152             
153                if (logger.isDebugEnabled())
154                   logger.debug("Pushed current view to stack: " + viewId);
155             }
156             else
157             {
158                if (getViewStack(context).empty() == false && logger.isDebugEnabled())
159                {
160                   logger.debug("current view is already top the view stack!");
161                }
162             }
163          }
164          
165          if (logger.isDebugEnabled())
166             logger.debug("view stack: " + getViewStack(context));
167       }
168       
169       if (closingDialog == false)
170       {
171          NavigationBean navBean = (NavigationBean)context.getExternalContext().
172             getSessionMap().get("NavigationBean");
173          
174          // only continue if we have some dispatching context
175
if (navBean != null && navBean.getDispatchContextNode() != null)
176          {
177             Node node = navBean.getDispatchContextNode();
178                   
179             if (logger.isDebugEnabled())
180                logger.debug("Found node with type '" + node.getType().toString() +
181                             "' in dispatch context");
182    
183             // see if there is any navigation config for the node type
184
ConfigService configSvc = Application.getConfigService(context);
185             Config nodeConfig = configSvc.getConfig(node);
186             NavigationConfigElement navigationCfg = (NavigationConfigElement)nodeConfig.
187                   getConfigElement(NavigationElementReader.ELEMENT_NAVIGATION);
188             
189             if (navigationCfg != null)
190             {
191                // see if there is config for the current view state
192
NavigationResult navResult = navigationCfg.getOverride(viewId, outcome);
193                
194                if (navResult != null)
195                {
196                   if (logger.isDebugEnabled())
197                      logger.debug("Found navigation config: " + navResult);
198                   
199                   if (navResult.isOutcome())
200                   {
201                      outcome = navResult.getResult();
202                   }
203                   else
204                   {
205                      String JavaDoc newViewId = navResult.getResult();
206                      
207                      if (newViewId.equals(viewId) == false)
208                      {
209                         useOriginalNavHandler = false;
210                         
211                         if (logger.isDebugEnabled())
212                            logger.debug("Dispatching to new view id: " + newViewId);
213                      
214                         goToView(context, newViewId);
215                      }
216                      else
217                      {
218                         if (logger.isDebugEnabled())
219                            logger.debug("New view id is the same as the current one so setting outcome to null");
220                         
221                         outcome = null;
222                      }
223                   }
224                }
225                else if (logger.isDebugEnabled())
226                {
227                   logger.debug("No override configuration found for current view or outcome");
228                }
229             }
230             else if (logger.isDebugEnabled())
231             {
232                logger.debug("No navigation configuration found for node");
233             }
234             
235             // reset the dispatch context
236
navBean.resetDispatchContext();
237          }
238          else if (logger.isDebugEnabled())
239          {
240             logger.debug("No dispatch context found");
241          }
242          
243          // do the appropriate navigation handling
244
if (useOriginalNavHandler)
245          {
246             if (logger.isDebugEnabled())
247                logger.debug("Passing outcome '" + outcome + "' to original navigation handler");
248             
249             this.origHandler.handleNavigation(context, fromAction, outcome);
250          }
251       }
252    }
253    
254    /**
255     * Dispatches to the given view id
256     *
257     * @param context Faces context
258     * @param viewId The view id to go to
259     */

260    private void goToView(FacesContext context, String JavaDoc viewId)
261    {
262       ViewHandler viewHandler = context.getApplication().getViewHandler();
263       UIViewRoot viewRoot = viewHandler.createView(context, viewId);
264       viewRoot.setViewId(viewId);
265       context.setViewRoot(viewRoot);
266       context.renderResponse();
267    }
268    
269    /**
270     * Returns the view stack for the current user.
271     *
272     * @param context FacesContext
273     * @return A Stack representing the views that have launched dialogs in
274     * the users session, will never be null
275     */

276    @SuppressWarnings JavaDoc("unchecked")
277    private Stack JavaDoc getViewStack(FacesContext context)
278    {
279       Stack JavaDoc viewStack = (Stack JavaDoc)context.getExternalContext().getSessionMap().get(VIEW_STACK);
280       
281       if (viewStack == null)
282       {
283          viewStack = new Stack JavaDoc();
284          context.getExternalContext().getSessionMap().put(VIEW_STACK, viewStack);
285       }
286       
287       return viewStack;
288    }
289 }
290
Popular Tags