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