View Javadoc

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 org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.myfaces.shared.renderkit.JSFAttr;
24  
25  import javax.faces.FacesException;
26  import javax.faces.component.NamingContainer;
27  import javax.faces.component.UIComponent;
28  import javax.faces.component.UISelectBoolean;
29  import javax.faces.component.UISelectMany;
30  import javax.faces.component.html.HtmlSelectBooleanCheckbox;
31  import javax.faces.component.html.HtmlSelectManyCheckbox;
32  import javax.faces.context.FacesContext;
33  import javax.faces.context.ResponseWriter;
34  import javax.faces.convert.Converter;
35  import javax.faces.convert.ConverterException;
36  import javax.faces.model.SelectItem;
37  import javax.faces.model.SelectItemGroup;
38  import java.io.IOException;
39  import java.util.Iterator;
40  import java.util.Set;
41  
42  /***
43   * @author Thomas Spiegl (latest modification by $Author: lu4242 $)
44   * @author Anton Koinov
45   * @version $Revision: 684924 $ $Date: 2008-08-11 15:59:26 -0500 (Mon, 11 Aug 2008) $
46   */
47  public class HtmlCheckboxRendererBase extends HtmlRenderer {
48      private static final Log log = LogFactory
49              .getLog(HtmlCheckboxRendererBase.class);
50  
51      private static final String PAGE_DIRECTION = "pageDirection";
52  
53      private static final String LINE_DIRECTION = "lineDirection";
54  
55      private static final String EXTERNAL_TRUE_VALUE = "true";
56  
57      public void encodeEnd(FacesContext facesContext, UIComponent uiComponent)
58              throws IOException {
59          org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, uiComponent, null);
60          if (uiComponent instanceof UISelectBoolean) {
61              Boolean value = org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanValue( uiComponent );
62              boolean isChecked = value != null ? value.booleanValue() : false;
63              renderCheckbox(facesContext, uiComponent, EXTERNAL_TRUE_VALUE, false,isChecked, true, null); //TODO: the selectBoolean is never disabled
64          } else if (uiComponent instanceof UISelectMany) {
65              renderCheckboxList(facesContext, (UISelectMany) uiComponent);
66          } else {
67              throw new IllegalArgumentException("Unsupported component class "
68                      + uiComponent.getClass().getName());
69          }
70      }
71  
72      public void renderCheckboxList(FacesContext facesContext,
73              UISelectMany selectMany) throws IOException {
74  
75          String layout = getLayout(selectMany);
76          boolean pageDirectionLayout = false; //Default to lineDirection
77          if (layout != null) {
78              if (layout.equals(PAGE_DIRECTION)) {
79                  pageDirectionLayout = true;
80              } else if (layout.equals(LINE_DIRECTION)) {
81                  pageDirectionLayout = false;
82              } else {
83                  log.error("Wrong layout attribute for component "
84                          + selectMany.getClientId(facesContext) + ": " + layout);
85              }
86          }
87  
88          ResponseWriter writer = facesContext.getResponseWriter();
89  
90          writer.startElement(HTML.TABLE_ELEM, selectMany);
91          HtmlRendererUtils.renderHTMLAttributes(writer, selectMany,
92                  HTML.SELECT_TABLE_PASSTHROUGH_ATTRIBUTES);
93          HtmlRendererUtils.writeIdIfNecessary(writer, selectMany, facesContext);
94  
95          if (!pageDirectionLayout)
96              writer.startElement(HTML.TR_ELEM, selectMany);
97          
98          Converter converter;
99          try {
100             converter = org.apache.myfaces.shared.renderkit.RendererUtils.findUISelectManyConverter(facesContext,
101                     selectMany);
102         } catch (FacesException e) {
103             log.error("Error finding Converter for component with id "
104                     + selectMany.getClientId(facesContext));
105             converter = null;
106         }
107 
108         Set lookupSet = org.apache.myfaces.shared.renderkit.RendererUtils.getSubmittedValuesAsSet(facesContext, selectMany, converter, selectMany);
109         boolean useSubmittedValues = lookupSet != null;
110 
111         if (!useSubmittedValues) {
112             lookupSet = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectedValuesAsSet(facesContext, selectMany, converter, selectMany);
113         }
114 
115         int itemNum = 0;
116 
117         for (Iterator it = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectMany)
118                 .iterator(); it.hasNext();) {
119             SelectItem selectItem = (SelectItem) it.next();
120             
121             renderGroupOrItemCheckbox(facesContext, selectMany, 
122                     selectItem, useSubmittedValues, lookupSet, 
123                     converter, pageDirectionLayout, new Integer(itemNum));
124 
125             itemNum++;
126         }
127 
128         if (!pageDirectionLayout)
129             writer.endElement(HTML.TR_ELEM);
130         writer.endElement(HTML.TABLE_ELEM);
131     }
132 
133     protected String getLayout(UISelectMany selectMany) {
134         if (selectMany instanceof HtmlSelectManyCheckbox) {
135             return ((HtmlSelectManyCheckbox) selectMany).getLayout();
136         } 
137         
138         return (String) selectMany.getAttributes().get(JSFAttr.LAYOUT_ATTR);
139     }
140     
141     protected void renderGroupOrItemCheckbox(FacesContext facesContext,
142                                              UIComponent uiComponent, SelectItem selectItem,
143                                              boolean useSubmittedValues, Set lookupSet,
144                                              Converter converter, boolean pageDirectionLayout, Integer itemNum) throws IOException
145     {
146 
147         ResponseWriter writer = facesContext.getResponseWriter();
148 
149         boolean isSelectItemGroup = (selectItem instanceof SelectItemGroup);
150 
151         Object itemValue = selectItem.getValue(); // TODO : Check here for getSubmittedValue. Look at RendererUtils.getValue
152 
153         UISelectMany selectMany = (UISelectMany) uiComponent;
154 
155         String itemStrValue = org.apache.myfaces.shared.renderkit.RendererUtils.getConvertedStringValue(facesContext, selectMany, converter, itemValue);
156 
157         if (isSelectItemGroup)
158         {
159             if (pageDirectionLayout)
160                 writer.startElement(HTML.TR_ELEM, selectMany);
161 
162             writer.startElement(HTML.TD_ELEM, selectMany);
163             writer.write(selectItem.getLabel());
164             writer.endElement(HTML.TD_ELEM);
165 
166             if (pageDirectionLayout)
167             {
168                 writer.endElement(HTML.TR_ELEM);
169                 writer.startElement(HTML.TR_ELEM, selectMany);
170             }
171             writer.startElement(HTML.TD_ELEM, selectMany);
172 
173             writer.startElement(HTML.TABLE_ELEM, selectMany);
174             writer.writeAttribute(HTML.BORDER_ATTR, "0", null);
175 
176             SelectItemGroup group = (SelectItemGroup) selectItem;
177             SelectItem[] selectItems = group.getSelectItems();
178 
179             for (int i = 0; i < selectItems.length; i++)
180             {
181                 renderGroupOrItemCheckbox(facesContext, selectMany, selectItems[i], useSubmittedValues, lookupSet, converter, pageDirectionLayout, new Integer(i));
182             }
183 
184             writer.endElement(HTML.TD_ELEM);
185             writer.endElement(HTML.TR_ELEM);
186             writer.endElement(HTML.TABLE_ELEM);
187             writer.endElement(HTML.TD_ELEM);
188 
189             if (pageDirectionLayout)
190                 writer.endElement(HTML.TR_ELEM);
191 
192         }
193         else
194         {
195 
196             writer.write("\t\t");
197             if (pageDirectionLayout)
198                 writer.startElement(HTML.TR_ELEM, selectMany);
199             writer.startElement(HTML.TD_ELEM, selectMany);
200 
201             boolean checked = lookupSet.contains(itemStrValue);
202 
203             boolean disabled = selectItem.isDisabled();
204 
205             String itemId = renderCheckbox(facesContext, selectMany, itemStrValue, disabled, checked, false, itemNum);
206 
207             // label element after the input
208             boolean componentDisabled = isDisabled(facesContext, selectMany);
209             boolean itemDisabled = (componentDisabled || disabled);
210 
211             HtmlRendererUtils.renderLabel(writer, selectMany, itemId, selectItem, itemDisabled);
212 
213             writer.endElement(HTML.TD_ELEM);
214             if (pageDirectionLayout)
215                 writer.endElement(HTML.TR_ELEM);
216         }
217     }
218 
219     @Deprecated
220     protected void renderCheckbox(FacesContext facesContext,
221             UIComponent uiComponent, String value, String label,
222             boolean disabled, boolean checked, boolean renderId) throws IOException {
223         renderCheckbox(facesContext, uiComponent, value, disabled, checked, renderId, 0);
224     }
225 
226     /***
227      * Renders the input item
228      * @return the 'id' value of the rendered element
229      */
230     protected String renderCheckbox(FacesContext facesContext,
231             UIComponent uiComponent, String value, boolean disabled, boolean checked, boolean renderId, Integer itemNum) throws IOException {
232         String clientId = uiComponent.getClientId(facesContext);
233 
234         String itemId = (itemNum == null)? null : clientId + NamingContainer.SEPARATOR_CHAR + itemNum;
235 
236         ResponseWriter writer = facesContext.getResponseWriter();
237 
238         writer.startElement(HTML.INPUT_ELEM, uiComponent);
239 
240         if (itemId != null)
241         {
242             writer.writeAttribute(HTML.ID_ATTR, itemId, null);
243         }
244         writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_CHECKBOX, null);
245         writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
246         
247         if (renderId) {
248             HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent, facesContext);
249         }
250 
251         if (checked) {
252             writer.writeAttribute(HTML.CHECKED_ATTR, org.apache.myfaces.shared.renderkit.html.HTML.CHECKED_ATTR, null);
253         }
254         
255         if (disabled) {
256             writer.writeAttribute(HTML.DISABLED_ATTR, HTML.DISABLED_ATTR, null);
257         }
258 
259         if ((value != null) && (value.length() > 0)) {
260             writer.writeAttribute(HTML.VALUE_ATTR, value, null);
261         }
262 
263         if (uiComponent instanceof UISelectBoolean)
264         {
265             HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
266                 HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
267         }
268         else
269         {
270             HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
271                 HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_STYLE);
272         }
273         if (isDisabled(facesContext, uiComponent)) {
274             writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
275         }
276         
277         writer.endElement(HTML.INPUT_ELEM);
278 
279         return itemId;
280     }
281 
282     protected boolean isDisabled(FacesContext facesContext,
283             UIComponent component) {
284         //TODO: overwrite in extended HtmlCheckboxRenderer and check for
285         // enabledOnUserRole
286         if (component instanceof HtmlSelectBooleanCheckbox) {
287             return ((HtmlSelectBooleanCheckbox) component).isDisabled();
288         } else if (component instanceof HtmlSelectManyCheckbox) {
289             return ((HtmlSelectManyCheckbox) component).isDisabled();
290         } else {
291             return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component,
292                     HTML.DISABLED_ATTR, false);
293         }
294     }
295 
296     public void decode(FacesContext facesContext, UIComponent component) {
297         org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, component, null);
298         if (component instanceof UISelectBoolean) {
299             HtmlRendererUtils.decodeUISelectBoolean(facesContext, component);
300         } else if (component instanceof UISelectMany) {
301             HtmlRendererUtils.decodeUISelectMany(facesContext, component);
302         } else {
303             throw new IllegalArgumentException("Unsupported component class "
304                     + component.getClass().getName());
305         }
306     }
307 
308     public Object getConvertedValue(FacesContext facesContext,
309             UIComponent component, Object submittedValue)
310             throws ConverterException {
311         org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext, component, null);
312         if (component instanceof UISelectBoolean) {
313             return submittedValue;
314         } else if (component instanceof UISelectMany) {
315             return org.apache.myfaces.shared.renderkit.RendererUtils.getConvertedUISelectManyValue(facesContext,
316                     (UISelectMany) component, submittedValue);
317         } else {
318             throw new IllegalArgumentException("Unsupported component class "
319                     + component.getClass().getName());
320         }
321     }
322 }