Coverage Report - org.apache.myfaces.shared.renderkit.html.HtmlGridRendererBase
 
Classes in this File Line Coverage Branch Coverage Complexity
HtmlGridRendererBase
0%
0/139
0%
0/102
7.5
 
 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;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.logging.Level;
 25  
 import java.util.logging.Logger;
 26  
 
 27  
 import javax.faces.application.ProjectStage;
 28  
 import javax.faces.component.UIComponent;
 29  
 import javax.faces.component.UIPanel;
 30  
 import javax.faces.component.behavior.ClientBehavior;
 31  
 import javax.faces.component.behavior.ClientBehaviorHolder;
 32  
 import javax.faces.component.html.HtmlPanelGrid;
 33  
 import javax.faces.context.FacesContext;
 34  
 import javax.faces.context.ResponseWriter;
 35  
 
 36  
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 37  
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 38  
 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
 39  
 import org.apache.myfaces.shared.util.ArrayUtils;
 40  
 import org.apache.myfaces.shared.util.StringUtils;
 41  
 
 42  
 
 43  0
 public class HtmlGridRendererBase
 44  
         extends HtmlRenderer
 45  
 {
 46  
     //private static final Log log = LogFactory.getLog(HtmlGridRendererBase.class);
 47  0
     private static final Logger log = Logger.getLogger(HtmlGridRendererBase.class.getName());
 48  
     
 49  0
     private static final Integer[] ZERO_INT_ARRAY = new Integer[]{0};
 50  
 
 51  
     public boolean getRendersChildren()
 52  
     {
 53  0
         return true;
 54  
     }
 55  
 
 56  
     @Override
 57  
     public void decode(FacesContext context, UIComponent component)
 58  
     {
 59  
         // Check for npe
 60  0
         super.decode(context, component);
 61  
         
 62  0
         HtmlRendererUtils.decodeClientBehaviors(context, component);
 63  0
     }
 64  
 
 65  
     public void encodeBegin(FacesContext facesContext, UIComponent component)
 66  
             throws IOException
 67  
     {
 68  
         // all work done in encodeEnd()
 69  0
     }
 70  
 
 71  
     public void encodeChildren(FacesContext context, UIComponent component)
 72  
         throws IOException
 73  
     {
 74  
         // all work done in encodeEnd()
 75  0
     }
 76  
 
 77  
     public void encodeEnd(FacesContext facesContext, UIComponent component)
 78  
             throws IOException
 79  
     {
 80  0
         RendererUtils.checkParamValidity(facesContext, component, UIPanel.class);
 81  
 
 82  
         int columns;
 83  0
         if (component instanceof HtmlPanelGrid)
 84  
         {
 85  0
             columns = ((HtmlPanelGrid)component).getColumns();
 86  
         }
 87  
         else
 88  
         {
 89  0
             Integer i = (Integer)component.getAttributes().get(
 90  
                     org.apache.myfaces.shared.renderkit.JSFAttr.COLUMNS_ATTR);
 91  0
             columns = i != null ? i.intValue() : 0;
 92  
         }
 93  
 
 94  0
         if (columns <= 0)
 95  
         {
 96  0
             if (log.isLoggable(Level.SEVERE))
 97  
             {
 98  0
                 log.severe("Wrong columns attribute for PanelGrid " + 
 99  
                         component.getClientId(facesContext) + ": " + columns);
 100  
             }
 101  0
             columns = 1;
 102  
         }
 103  
 
 104  0
         ResponseWriter writer = facesContext.getResponseWriter();
 105  0
         Map<String, List<ClientBehavior>> behaviors = null;
 106  0
         if (component instanceof ClientBehaviorHolder)
 107  
         {
 108  0
             behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
 109  
         }
 110  
 
 111  0
         if (behaviors != null && !behaviors.isEmpty())
 112  
         {
 113  0
             ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
 114  
         }
 115  
         
 116  0
         writer.startElement(HTML.TABLE_ELEM, component);
 117  
         
 118  0
         if (component instanceof ClientBehaviorHolder)
 119  
         {
 120  0
             if (!behaviors.isEmpty())
 121  
             {
 122  0
                 HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
 123  
             }
 124  
             else
 125  
             {
 126  0
                 HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
 127  
             }
 128  0
             long commonPropertiesMarked = 0L;
 129  0
             if (isCommonPropertiesOptimizationEnabled(facesContext))
 130  
             {
 131  0
                 commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
 132  
             }
 133  0
             if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
 134  
             {
 135  0
                 CommonPropertyUtils.renderEventProperties(writer, 
 136  
                         commonPropertiesMarked, component);
 137  
             }
 138  
             else
 139  
             {
 140  0
                 if (isCommonEventsOptimizationEnabled(facesContext))
 141  
                 {
 142  0
                     CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
 143  
                            commonPropertiesMarked,
 144  
                            CommonEventUtils.getCommonEventsMarked(component), component, behaviors);
 145  
                 }
 146  
                 else
 147  
                 {
 148  0
                     HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, behaviors);
 149  
                 }
 150  
             }
 151  0
             if (isCommonPropertiesOptimizationEnabled(facesContext))
 152  
             {
 153  0
                 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_ATTRIBUTES);
 154  0
                 CommonPropertyUtils.renderCommonPassthroughPropertiesWithoutEvents(writer, 
 155  
                         commonPropertiesMarked, component);
 156  
             }
 157  
             else
 158  
             {
 159  0
                 HtmlRendererUtils.renderHTMLAttributes(writer, component, 
 160  
                         HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
 161  
             }
 162  0
         }
 163  
         else
 164  
         {
 165  0
             HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
 166  0
             if (isCommonPropertiesOptimizationEnabled(facesContext))
 167  
             {
 168  0
                 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_ATTRIBUTES);
 169  0
                 CommonPropertyUtils.renderCommonPassthroughProperties(writer, 
 170  
                         CommonPropertyUtils.getCommonPropertiesMarked(component), component);
 171  
             }
 172  
             else
 173  
             {
 174  0
                 HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
 175  
             }
 176  
         }
 177  
 
 178  0
         writer.flush();
 179  
 
 180  0
         HtmlRendererUtils.renderTableCaption(facesContext, writer, component);
 181  
 
 182  
         // theader and tfooter are rendered before the tbody
 183  0
         renderHeaderOrFooter(facesContext, writer, component, columns, true);   //Header facet
 184  0
         renderHeaderOrFooter(facesContext, writer, component, columns, false);  //Footer facet
 185  
         
 186  0
         renderChildren(facesContext, writer, component, columns);
 187  
 
 188  0
         writer.endElement(HTML.TABLE_ELEM);
 189  0
     }
 190  
 
 191  
     
 192  
 
 193  
     protected void renderHeaderOrFooter(FacesContext context,
 194  
                                       ResponseWriter writer,
 195  
                                       UIComponent component,
 196  
                                       int columns,
 197  
                                       boolean header)
 198  
         throws IOException
 199  
     {
 200  0
         UIComponent facet = component.getFacet(header ? "header" : "footer");
 201  0
         if (facet == null)
 202  
         {
 203  0
             return;
 204  
         }
 205  
 
 206  0
         writer.startElement(
 207  
                 header ? org.apache.myfaces.shared.renderkit.html.HTML.THEAD_ELEM : HTML.TFOOT_ELEM, null);
 208  
                 // component);
 209  0
         writer.startElement(HTML.TR_ELEM, null); // component);
 210  0
         writer.startElement(header ? HTML.TH_ELEM : HTML.TD_ELEM, null); // component);
 211  
 
 212  0
         String styleClass = (component instanceof HtmlPanelGrid)
 213  
             ? (header ?
 214  
                          ((HtmlPanelGrid)component).getHeaderClass() :
 215  
                          ((HtmlPanelGrid)component).getFooterClass())
 216  
             : (header ?
 217  
                          (String)component.getAttributes().get(JSFAttr.HEADER_CLASS_ATTR) :
 218  
                          (String)component.getAttributes().get(
 219  
                                  org.apache.myfaces.shared.renderkit.JSFAttr.FOOTER_CLASS_ATTR));
 220  0
         if (styleClass != null)
 221  
         {
 222  0
             writer.writeAttribute(HTML.CLASS_ATTR, styleClass,
 223  
                                   header ? JSFAttr.HEADER_CLASS_ATTR : 
 224  
                                       org.apache.myfaces.shared.renderkit.JSFAttr.FOOTER_CLASS_ATTR);
 225  
         }
 226  
 
 227  0
         if (header)
 228  
         {
 229  0
             writer.writeAttribute(HTML.SCOPE_ATTR, HTML.SCOPE_COLGROUP_VALUE, null);
 230  
         }
 231  
 
 232  0
         writer.writeAttribute(HTML.COLSPAN_ATTR, Integer.toString(columns), null);
 233  
 
 234  
         //RendererUtils.renderChild(context, facet);
 235  0
         facet.encodeAll(context);
 236  
 
 237  0
         writer.endElement(header ? HTML.TH_ELEM : HTML.TD_ELEM);
 238  0
         writer.endElement(HTML.TR_ELEM);
 239  0
         writer.endElement(header ? HTML.THEAD_ELEM : HTML.TFOOT_ELEM);
 240  0
     }
 241  
 
 242  
     protected int childAttributes(FacesContext context,
 243  
             ResponseWriter writer,
 244  
             UIComponent component,
 245  
             int columnIndex)
 246  
         throws IOException
 247  
     {
 248  
         // subclasses can override this method to add attributes to the table cell <td> tag
 249  0
         return columnIndex;
 250  
     }
 251  
 
 252  
     protected void renderChildren(FacesContext context,
 253  
                                 ResponseWriter writer,
 254  
                                 UIComponent component,
 255  
                                 int columns)
 256  
         throws IOException
 257  
     {
 258  
         String columnClasses;
 259  
         String rowClasses;
 260  0
         if (component instanceof HtmlPanelGrid)
 261  
         {
 262  0
             columnClasses = ((HtmlPanelGrid)component).getColumnClasses();
 263  0
             rowClasses =  ((HtmlPanelGrid)component).getRowClasses();
 264  
         }
 265  
         else
 266  
         {
 267  0
             columnClasses = (String)component.getAttributes().get(
 268  
                     org.apache.myfaces.shared.renderkit.JSFAttr.COLUMN_CLASSES_ATTR);
 269  0
             rowClasses = (String)component.getAttributes().get(JSFAttr.ROW_CLASSES_ATTR);
 270  
         }
 271  
 
 272  0
         String[] columnClassesArray = (columnClasses == null)
 273  
             ? ArrayUtils.EMPTY_STRING_ARRAY
 274  
             : StringUtils.trim(StringUtils.splitShortString(columnClasses, ','));
 275  0
         int columnClassesCount = columnClassesArray.length;
 276  
 
 277  0
         String[] rowClassesArray = (rowClasses == null)
 278  
             ? org.apache.myfaces.shared.util.ArrayUtils.EMPTY_STRING_ARRAY
 279  
             : StringUtils.trim(StringUtils.splitShortString(rowClasses, ','));
 280  0
         int rowClassesCount = rowClassesArray.length;
 281  
 
 282  0
         int childCount = getChildCount(component);
 283  0
         if (childCount > 0)
 284  
         {
 285  
             // get the row indizes for which a new TBODY element should be created
 286  0
             Integer[] bodyrows = null;
 287  0
             String bodyrowsAttr = (String) component.getAttributes().get(JSFAttr.BODYROWS_ATTR);
 288  0
             if(bodyrowsAttr != null && !"".equals(bodyrowsAttr)) 
 289  
             {   
 290  0
                 String[] bodyrowsString = StringUtils.trim(StringUtils.splitShortString(bodyrowsAttr, ','));
 291  
                 // parsing with no exception handling, because of JSF-spec: 
 292  
                 // "If present, this must be a comma separated list of integers."
 293  0
                 bodyrows = new Integer[bodyrowsString.length];
 294  0
                 for(int i = 0; i < bodyrowsString.length; i++) 
 295  
                 {
 296  0
                     bodyrows[i] = Integer.valueOf(bodyrowsString[i]);
 297  
                 }
 298  
                 
 299  0
             }
 300  
             else
 301  
             {
 302  0
                 bodyrows = ZERO_INT_ARRAY;
 303  
             }
 304  0
             int bodyrowsCount = 0;
 305  0
             int rowIndex = -1;
 306  0
             int columnIndex = 0;
 307  0
             int rowClassIndex = 0;
 308  0
             boolean rowStarted = false;
 309  0
             for (int i = 0, size =  component.getChildCount(); i < size; i++)
 310  
             {
 311  0
                 UIComponent child = component.getChildren().get(i);
 312  0
                 if (child.isRendered())
 313  
                 {
 314  0
                     if (columnIndex == 0)
 315  
                     {
 316  0
                         rowIndex++;
 317  
                         
 318  0
                         if (rowStarted)
 319  
                         {
 320  
                             //do we have to close the last row?
 321  0
                             writer.endElement(HTML.TR_ELEM);
 322  
                         }
 323  
                         
 324  
                         // is the current row listed in the bodyrows attribute
 325  0
                         if(ArrayUtils.contains(bodyrows, rowIndex)) 
 326  
                         {
 327  
                             // close any preopened TBODY element first
 328  0
                             if(bodyrowsCount != 0) 
 329  
                             {
 330  0
                                 writer.endElement(HTML.TBODY_ELEM);
 331  
                             }
 332  0
                             writer.startElement(HTML.TBODY_ELEM, null); // component); 
 333  0
                             bodyrowsCount++;
 334  
                         }
 335  
                         
 336  
                         //start of new/next row
 337  0
                         writer.startElement(HTML.TR_ELEM, null); // component);
 338  0
                         if (rowClassIndex < rowClassesCount)
 339  
                         {
 340  0
                             writer.writeAttribute(HTML.CLASS_ATTR, rowClassesArray[rowClassIndex], null);
 341  
                         }
 342  0
                         rowStarted = true;
 343  0
                         rowClassIndex++;
 344  0
                         if (rowClassIndex == rowClassesCount)
 345  
                         {
 346  0
                             rowClassIndex = 0;
 347  
                         }
 348  
                     }
 349  
 
 350  0
                     writer.startElement(HTML.TD_ELEM, null); // component);
 351  0
                     if (columnIndex < columnClassesCount)
 352  
                     {
 353  0
                         writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
 354  
                     }
 355  0
                     columnIndex = childAttributes(context, writer, child, columnIndex);
 356  
                     //RendererUtils.renderChild(context, child);
 357  0
                     child.encodeAll(context);
 358  0
                     writer.endElement(HTML.TD_ELEM);
 359  
 
 360  0
                     columnIndex++;
 361  0
                     if (columnIndex >= columns)
 362  
                     {
 363  0
                         columnIndex = 0;
 364  
                     }
 365  
                 }
 366  
             }
 367  
 
 368  0
             if (rowStarted)
 369  
             {
 370  0
                 if (columnIndex > 0)
 371  
                 {
 372  0
                     Level level = context.isProjectStage(ProjectStage.Production) ? Level.FINE : Level.WARNING;
 373  0
                     if (log.isLoggable(level))
 374  
                     {
 375  0
                         log.log(level, "PanelGrid " + RendererUtils.getPathToComponent(component) 
 376  
                                 + " has not enough children. Child count should be a " 
 377  
                                 + "multiple of the columns attribute.");
 378  
                     }
 379  
                     //Render empty columns, so that table is correct
 380  0
                     for ( ; columnIndex < columns; columnIndex++)
 381  
                     {
 382  0
                         writer.startElement(HTML.TD_ELEM, null); // component);
 383  0
                         if (columnIndex < columnClassesCount)
 384  
                         {
 385  0
                             writer.writeAttribute(HTML.CLASS_ATTR, columnClassesArray[columnIndex], null);
 386  
                         }
 387  0
                         writer.endElement(HTML.TD_ELEM);
 388  
                     }
 389  
                 }
 390  0
                 writer.endElement(HTML.TR_ELEM);
 391  
                 
 392  
                 // close any preopened TBODY element first
 393  0
                 if(bodyrowsCount != 0) 
 394  
                 {
 395  0
                     writer.endElement(HTML.TBODY_ELEM);
 396  
                 }
 397  
             }
 398  
         }
 399  0
     }
 400  
 
 401  
 }