You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by cj...@apache.org on 2009/08/12 15:29:04 UTC

svn commit: r803498 - in /myfaces/core/trunk/impl/src/main/java/org/apache/myfaces: application/NavigationHandlerImpl.java view/facelets/tag/jsf/html/HtmlLibrary.java

Author: cjhoward
Date: Wed Aug 12 13:29:04 2009
New Revision: 803498

URL: http://svn.apache.org/viewvc?rev=803498&view=rev
Log:
MYFACES-2302 - add support for the rest of the NavigationHandler algorithm

Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/HtmlLibrary.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java?rev=803498&r1=803497&r2=803498&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/NavigationHandlerImpl.java Wed Aug 12 13:29:04 2009
@@ -176,9 +176,132 @@
             }
         }
         
+        if (navigationCase == null)
+        {
+            // Still can't find a navigation case, so we need to look at the outcome and see what navigation case
+            // can be determined from it.
+            
+            navigationCase = getOutcomeNavigationCase (facesContext, fromAction, outcome);
+        }
+        
         return navigationCase;
     }
-
+    
+    /**
+     * Performs the algorithm specified in 7.4.2 for situations where no navigation cases are defined and instead
+     * the navigation case is to be determined from the outcome.
+     * 
+     * TODO: cache results?
+     */
+    
+    private NavigationCase getOutcomeNavigationCase (FacesContext facesContext, String fromAction, String outcome)
+    {
+        String implicitViewId = null;
+        boolean includeViewParams = false;
+        int index;
+        boolean isRedirect = false;
+        String queryString = null;
+        NavigationCase result = null;
+        String viewId = facesContext.getViewRoot().getViewId();
+        String viewIdToTest = outcome;
+        
+        // If viewIdToTest contains a query string, remove it and set queryString with that value.
+        
+        index = viewIdToTest.indexOf ("?");
+        
+        if (index != -1)
+        {
+            queryString = viewIdToTest.substring (index + 1);
+            viewIdToTest = viewIdToTest.substring (0, index);
+            
+            // If queryString contains "faces-redirect=true", set isRedirect to true.
+            
+            if (queryString.indexOf ("faces-redirect=true") != -1)
+            {
+                isRedirect = true;
+            }
+            
+            // If queryString contains "includeViewParams=true", set includeViewParams to true.
+            
+            if (queryString.indexOf ("includeViewParams=true") != -1)
+            {
+                includeViewParams = true;
+            }
+        }
+        
+        // FIXME: the spec states that redirection (i.e., isRedirect=true) is implied when preemptive navigation is performed,
+        // though I'm not sure how we're supposed to determine that.
+        
+        // If viewIdToTest does not have a "file extension", use the one from the current viewId.
+        // TODO: I don't know exactly what the spec means by "file extension".  I'm assuming everything after "."
+        
+        index = viewIdToTest.indexOf (".");
+        
+        if (index == -1)
+        {
+            index = viewId.indexOf (".");
+            
+            if (index != -1)
+            {
+                viewIdToTest += viewId.substring (index);
+            }
+        }
+        
+        // If viewIdToTest does not start with "/", look for the last "/" in viewId.  If not found, simply prepend "/".
+        // Otherwise, prepend everything before and including the last "/" in viewId.
+        
+        if (!viewIdToTest.startsWith ("/"))
+        {
+            index = viewId.lastIndexOf ("/");
+            
+            if (index == -1)
+            {
+                viewIdToTest = "/" + viewIdToTest;
+            }
+            
+            else
+            {
+                viewIdToTest = viewId.substring (0, index + 1) + viewIdToTest;
+            }
+        }
+        
+        // Call ViewHandler.deriveViewId() and set the result as implicitViewId.
+        
+        try
+        {
+            implicitViewId = facesContext.getApplication().getViewHandler().deriveViewId (facesContext, viewIdToTest);
+        }
+        
+        catch (UnsupportedOperationException e)
+        {
+            // This is the case when a pre-JSF 2.0 ViewHandler is used.  In this case, the default algorithm must be used.
+            // FIXME: I think we're always calling the "default" ViewHandler.deriveViewId() algorithm and we don't
+            // distinguish between pre-JSF 2.0 and JSF 2.0 ViewHandlers.  This probably needs to be addressed.
+        }
+        
+        if (implicitViewId != null)
+        {
+            Map<String, List<String>> params = new HashMap<String, List<String>>();
+            
+            // Append queryString to implicitViewId if it exists.
+            
+            if (queryString != null)
+            {
+                implicitViewId += "?" + queryString;
+            }
+            
+            // Finally, create the NavigationCase.
+            
+            // FIXME: the spec doesn't really say how the redirect parameters are supposed to be
+            // populated.  Assuming for now that they should stay empty...
+            
+            result = new NavigationCase (viewId, fromAction, outcome, null, implicitViewId, params,
+                isRedirect, includeViewParams);
+        }
+        
+        return result;
+    }
+    
     /**
      * Returns the view ID that would be created for the given action and outcome
      */

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/HtmlLibrary.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/HtmlLibrary.java?rev=803498&r1=803497&r2=803498&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/HtmlLibrary.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/html/HtmlLibrary.java Wed Aug 12 13:29:04 2009
@@ -35,6 +35,8 @@
         
         this.addHtmlComponent ("body", "javax.faces.OutputBody", "javax.faces.Body");
         
+        this.addHtmlComponent ("button", "javax.faces.HtmlOutcomeTargetButton", "javax.faces.Button");
+        
         this.addHtmlComponent("column", "javax.faces.Column", null);
 
         this.addHtmlComponent("commandButton", "javax.faces.HtmlCommandButton", "javax.faces.Button");
@@ -56,7 +58,9 @@
         this.addHtmlComponent("inputText", "javax.faces.HtmlInputText", "javax.faces.Text");
 
         this.addHtmlComponent("inputTextarea", "javax.faces.HtmlInputTextarea", "javax.faces.Textarea");
-
+        
+        this.addHtmlComponent ("link", "javax.faces.HtmlOutcomeTargetLink", "javax.faces.Link");
+        
         this.addHtmlComponent("message", "javax.faces.HtmlMessage", "javax.faces.Message");
 
         this.addHtmlComponent("messages", "javax.faces.HtmlMessages", "javax.faces.Messages");