Coverage Report - org.apache.myfaces.shared.renderkit.html.util.OutcomeTargetUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
OutcomeTargetUtils
0%
0/87
0%
0/78
14.333
 
 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.shared.renderkit.html.util;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collections;
 24  
 import java.util.HashMap;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 import java.util.logging.Level;
 28  
 import java.util.logging.Logger;
 29  
 import javax.faces.FacesException;
 30  
 import javax.faces.application.ConfigurableNavigationHandler;
 31  
 import javax.faces.application.NavigationCase;
 32  
 import javax.faces.application.NavigationHandler;
 33  
 import javax.faces.application.ProjectStage;
 34  
 import javax.faces.application.ViewHandler;
 35  
 import javax.faces.component.UIComponent;
 36  
 import javax.faces.component.UIOutcomeTarget;
 37  
 import javax.faces.component.UIParameter;
 38  
 import javax.faces.context.FacesContext;
 39  
 import javax.faces.flow.FlowHandler;
 40  
 import javax.faces.lifecycle.ClientWindow;
 41  
 import org.apache.myfaces.shared.application.NavigationUtils;
 42  
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 43  
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 44  
 import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
 45  
 
 46  
 /**
 47  
  * Utility methods for OutcomeTarget components.
 48  
  */
 49  0
 public class OutcomeTargetUtils
 50  
 {
 51  
     
 52  0
     private static final Logger log = Logger.getLogger(OutcomeTargetUtils.class
 53  
             .getName());
 54  
     
 55  
     public static String getOutcomeTargetHref(FacesContext facesContext,
 56  
             UIOutcomeTarget component) throws IOException
 57  
     {
 58  0
         String outcome = component.getOutcome();
 59  0
         outcome = (outcome == null) ? facesContext.getViewRoot().getViewId()
 60  
                 : outcome;
 61  0
         outcome = ((outcome == null) ? HtmlRendererUtils.STR_EMPTY : outcome.trim());
 62  
         // Get the correct URL for the outcome.
 63  0
         NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
 64  0
         if (!(nh instanceof ConfigurableNavigationHandler))
 65  
         {
 66  0
             throw new FacesException(
 67  
                     "Navigation handler must be an instance of "
 68  
                             + "ConfigurableNavigationHandler for using h:link or h:button");
 69  
         }
 70  0
         ConfigurableNavigationHandler navigationHandler = (ConfigurableNavigationHandler) nh;
 71  
         
 72  
         // handle faces flow 
 73  
         // 1. check to-flow-document-id
 74  0
         String toFlowDocumentId = (String) component.getAttributes().get(
 75  
             JSFAttr.TO_FLOW_DOCUMENT_ID_ATTR);
 76  
         
 77  
         // fromAction is null because there is no action method that was called to get the outcome
 78  0
         NavigationCase navigationCase = null;
 79  0
         if (toFlowDocumentId == null)
 80  
         {
 81  0
             navigationCase = navigationHandler.getNavigationCase(
 82  
                 facesContext, null, outcome);
 83  
         }
 84  
         else
 85  
         {
 86  0
             navigationCase = navigationHandler.getNavigationCase(
 87  
                 facesContext, null, outcome, toFlowDocumentId);            
 88  
         }
 89  
         
 90  
         // when navigation case is null, force the link or button to be disabled and log a warning
 91  0
         if (navigationCase == null)
 92  
         {
 93  
             // log a warning
 94  0
             log.warning("Could not determine NavigationCase for UIOutcomeTarget component "
 95  
                     + RendererUtils.getPathToComponent(component) + " with outcome " + outcome);
 96  
 
 97  0
             return null;
 98  
         }
 99  0
         Map<String, List<String>> parameters = null;
 100  
         // handle URL parameters
 101  0
         if (component.getChildCount() > 0)
 102  
         {
 103  0
             List<UIParameter> validParams = getValidUIParameterChildren(
 104  
                     facesContext, component.getChildren(), true, false);
 105  0
             if (validParams.size() > 0)
 106  
             {
 107  0
                 parameters = new HashMap<String, List<String>>();
 108  
             }
 109  0
             for (int i = 0, size = validParams.size(); i < size; i++)
 110  
             {
 111  0
                 UIParameter param = validParams.get(i);
 112  0
                 String name = param.getName();
 113  0
                 Object value = param.getValue();
 114  0
                 if (parameters.containsKey(name))
 115  
                 {
 116  0
                     parameters.get(name).add(value.toString());
 117  
                 }
 118  
                 else
 119  
                 {
 120  0
                     List<String> list = new ArrayList<String>(1);
 121  0
                     list.add(value.toString());
 122  0
                     parameters.put(name, list);
 123  
                 }
 124  
             }
 125  
         }
 126  
         
 127  
         // From the navigation case, use getToFlowDocumentId() to identify when
 128  
         // a navigation case is a flow call or a flow return.
 129  0
         if (navigationCase.getToFlowDocumentId() != null)
 130  
         {
 131  0
             if (parameters == null)
 132  
             {
 133  0
                 parameters = new HashMap<String, List<String>>();
 134  
             }
 135  0
             if (!parameters.containsKey(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME))
 136  
             {
 137  0
                 List<String> list = new ArrayList<String>(1);
 138  0
                 list.add(navigationCase.getToFlowDocumentId());
 139  0
                 parameters.put(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, list);
 140  
             }
 141  0
             if (!parameters.containsKey(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME))
 142  
             {
 143  0
                 List<String> list2 = new ArrayList<String>(1);
 144  0
                 list2.add(navigationCase.getFromOutcome());
 145  0
                 parameters.put(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, list2);
 146  
             }
 147  
         }
 148  
         
 149  
         // handle NavigationCase parameters
 150  0
         Map<String, List<String>> navigationCaseParams = 
 151  
             NavigationUtils.getEvaluatedNavigationParameters(facesContext,
 152  
                 navigationCase.getParameters());
 153  0
         if (navigationCaseParams != null)
 154  
         {
 155  0
             if (parameters == null)
 156  
             {
 157  0
                 parameters = new HashMap<String, List<String>>();
 158  
             }
 159  
             //parameters.putAll(navigationCaseParams);
 160  0
             for (Map.Entry<String, List<String>> entry : navigationCaseParams
 161  
                     .entrySet())
 162  
             {
 163  0
                 if (!parameters.containsKey(entry.getKey()))
 164  
                 {
 165  0
                     parameters.put(entry.getKey(), entry.getValue());
 166  
                 }
 167  0
             }
 168  
         }
 169  0
         if (parameters == null)
 170  
         {
 171  0
             parameters = Collections.emptyMap();
 172  
         }
 173  0
         boolean disableClientWindow = component.isDisableClientWindow();
 174  0
         ClientWindow clientWindow = facesContext.getExternalContext().getClientWindow();
 175  
         String href;
 176  
         try
 177  
         {
 178  0
             if (clientWindow != null && disableClientWindow)
 179  
             {
 180  0
                 clientWindow.disableClientWindowRenderMode(facesContext);
 181  
             }
 182  
             // In theory the precedence order to deal with params is this:
 183  
             // component parameters, navigation-case parameters, view parameters
 184  
             // getBookmarkableURL deal with this details.
 185  0
             ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
 186  0
             href = viewHandler.getBookmarkableURL(facesContext,
 187  
                     navigationCase.getToViewId(facesContext),
 188  
                     parameters, navigationCase.isIncludeViewParams() || component.isIncludeViewParams());
 189  
         }
 190  
         finally
 191  
         {
 192  0
             if (clientWindow != null && disableClientWindow)
 193  
             {
 194  0
                 clientWindow.enableClientWindowRenderMode(facesContext);
 195  
             }
 196  
         }
 197  
         // handle fragment (viewId#fragment)
 198  0
         String fragment = (String) component.getAttributes().get("fragment");
 199  0
         if (fragment != null)
 200  
         {
 201  0
             fragment = fragment.trim();
 202  
 
 203  0
             if (fragment.length() > 0)
 204  
             {
 205  0
                 href += "#" + fragment;
 206  
             }
 207  
         }
 208  0
         return href;
 209  
     }
 210  
 
 211  
     /**
 212  
      * Calls getValidUIParameterChildren(facesContext, children, skipNullValue, skipUnrendered, true);
 213  
      *
 214  
      * @param facesContext
 215  
      * @param children
 216  
      * @param skipNullValue
 217  
      * @param skipUnrendered
 218  
      * @return ArrayList size > 0 if any parameter found
 219  
      */
 220  
     public static List<UIParameter> getValidUIParameterChildren(
 221  
             FacesContext facesContext, List<UIComponent> children,
 222  
             boolean skipNullValue, boolean skipUnrendered)
 223  
     {
 224  0
         return getValidUIParameterChildren(facesContext, children,
 225  
                 skipNullValue, skipUnrendered, true);
 226  
     }
 227  
     
 228  
     
 229  
     /**
 230  
      * Returns a List of all valid UIParameter children from the given children.
 231  
      * Valid means that the UIParameter is not disabled, its name is not null
 232  
      * (if skipNullName is true), its value is not null (if skipNullValue is true)
 233  
      * and it is rendered (if skipUnrendered is true). This method also creates a
 234  
      * warning for every UIParameter with a null-name (again, if skipNullName is true)
 235  
      * and, if ProjectStage is Development and skipNullValue is true, it informs the
 236  
      * user about every null-value.
 237  
      *
 238  
      * @param facesContext
 239  
      * @param children
 240  
      * @param skipNullValue  should UIParameters with a null value be skipped
 241  
      * @param skipUnrendered should UIParameters with isRendered() returning false be skipped
 242  
      * @param skipNullName   should UIParameters with a null name be skipped
 243  
      *                       (normally true, but in the case of h:outputFormat false)
 244  
      * @return ArrayList size > 0 if any parameter found 
 245  
      */
 246  
     public static List<UIParameter> getValidUIParameterChildren(
 247  
             FacesContext facesContext, List<UIComponent> children,
 248  
             boolean skipNullValue, boolean skipUnrendered, boolean skipNullName)
 249  
     {
 250  0
         List<UIParameter> params = null;
 251  0
         for (int i = 0, size = children.size(); i < size; i++)
 252  
         {
 253  0
             UIComponent child = children.get(i);
 254  0
             if (child instanceof UIParameter)
 255  
             {
 256  0
                 UIParameter param = (UIParameter) child;
 257  
                 // check for the disable attribute (since 2.0)
 258  
                 // and the render attribute (only if skipUnrendered is true)
 259  0
                 if (param.isDisable() || (skipUnrendered && !param.isRendered()))
 260  
                 {
 261  
                     // ignore this UIParameter and continue
 262  0
                     continue;
 263  
                 }
 264  
                 // check the name
 265  0
                 String name = param.getName();
 266  0
                 if (skipNullName && (name == null || HtmlRendererUtils.STR_EMPTY.equals(name)))
 267  
                 {
 268  
                     // warn for a null-name
 269  0
                     log.log(Level.WARNING, "The UIParameter " + RendererUtils.getPathToComponent(param)
 270  
                                     + " has a name of null or empty string and thus will not be added to the URL.");
 271  
                     // and skip it
 272  0
                     continue;
 273  
                 }
 274  
                 // check the value
 275  0
                 if (skipNullValue && param.getValue() == null)
 276  
                 {
 277  0
                     if (facesContext.isProjectStage(ProjectStage.Development))
 278  
                     {
 279  
                         // inform the user about the null value when in Development stage
 280  0
                         log.log(Level.INFO, "The UIParameter " + RendererUtils.getPathToComponent(param)
 281  
                                         + " has a value of null and thus will not be added to the URL.");
 282  
                     }
 283  
                     // skip a null-value
 284  
                     continue;
 285  
                 }
 286  
                 // add the param
 287  0
                 if (params == null)
 288  
                 {
 289  0
                     params = new ArrayList<UIParameter>();
 290  
                 }
 291  0
                 params.add(param);
 292  
             }
 293  
         }
 294  0
         if (params == null)
 295  
         {
 296  0
             params = Collections.emptyList();
 297  
         }
 298  0
         return params;
 299  
     }
 300  
 
 301  
 }