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.renderkit.html.ext;
20  
21  import java.io.IOException;
22  import java.util.List;
23  
24  import javax.faces.FacesException;
25  import javax.faces.component.NamingContainer;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIInput;
28  import javax.faces.component.UISelectOne;
29  import javax.faces.component.UIViewRoot;
30  import javax.faces.context.FacesContext;
31  import javax.faces.context.ResponseWriter;
32  import javax.faces.convert.Converter;
33  import javax.faces.model.SelectItem;
34  
35  import org.apache.myfaces.component.UserRoleUtils;
36  import org.apache.myfaces.custom.radio.HtmlRadio;
37  import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
38  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
39  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
40  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRadioRendererBase;
41  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
42  
43  
44  /**
45   * 
46   * @JSFRenderer
47   *   renderKitId = "HTML_BASIC"
48   *   family = "org.apache.myfaces.Radio"
49   *   type = "org.apache.myfaces.Radio"
50   *    
51   * @JSFRenderer
52   *   renderKitId = "HTML_BASIC"
53   *   family = "javax.faces.SelectOne"
54   *   type = "org.apache.myfaces.Radio"
55   * 
56   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
57   * @author Thomas Spiegl
58   * @version $Revision: 1084268 $ $Date: 2011-03-22 12:50:23 -0500 (Tue, 22 Mar 2011) $
59   */
60  public class HtmlRadioRenderer
61          extends HtmlRadioRendererBase
62  {
63      //private static final Log log = LogFactory.getLog(HtmlRadioRenderer.class);
64  
65      private static final String LAYOUT_SPREAD = "spread";
66  
67      public void encodeEnd(FacesContext context, UIComponent component) throws IOException
68      {
69          if (context == null) throw new NullPointerException("context");
70          if (component == null) throw new NullPointerException("component");
71  
72          if (component instanceof HtmlRadio)
73          {
74              renderRadio(context, (HtmlRadio)component);
75          }
76          else if (HtmlRendererUtils.isDisplayValueOnly(component))
77          {
78              HtmlRendererUtils.renderDisplayValueOnlyForSelects(context, component);
79          }
80          else if (component instanceof UISelectOne)
81          {
82              String layout = getLayout(component);
83              if (layout != null && layout.equals(LAYOUT_SPREAD))
84              {
85                  return; //radio inputs are rendered by spread radio components
86              }
87              else
88              {
89                  super.encodeEnd(context, component);
90              }
91          }
92          else
93          {
94              throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
95          }
96      }
97  
98      protected void renderRadio(FacesContext facesContext, HtmlRadio radio) throws IOException
99      {
100         String forAttr = radio.getFor();
101         if (forAttr == null)
102         {
103             throw new IllegalStateException("mandatory attribute 'for'");
104         }
105         int index = radio.getIndex();
106         if (index < 0)
107         {
108             throw new IllegalStateException("positive index must be given");
109         }
110 
111         UIComponent uiComponent = radio.findComponent(forAttr);
112         if (uiComponent == null)
113         {
114             throw new IllegalStateException("Could not find component '" + forAttr + "' (calling findComponent on component '" + radio.getClientId(facesContext) + "')");
115         }
116         if (!(uiComponent instanceof UISelectOne))
117         {
118             throw new IllegalStateException("UISelectOne expected");
119         }
120 
121         UISelectOne uiSelectOne = (UISelectOne)uiComponent;
122         Converter converter;
123         List selectItemList = RendererUtils.getSelectItemList(uiSelectOne);
124         if (index >= selectItemList.size())
125         {
126             throw new IndexOutOfBoundsException("index " + index + " >= " + selectItemList.size());
127         }
128 
129         try
130         {
131             converter = RendererUtils.findUIOutputConverter(facesContext, uiSelectOne);
132         }
133         catch (FacesException e)
134         {
135             converter = null;
136         }
137 
138         Object currentValue = RendererUtils.getObjectValue(uiSelectOne);
139         currentValue
140             = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
141                                                     converter, currentValue);
142         SelectItem selectItem = (SelectItem)selectItemList.get(index);
143         String itemStrValue
144             = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
145                                                     converter,
146                                                     selectItem.getValue());
147 
148         ResponseWriter writer = facesContext.getResponseWriter();
149 
150         //writer.startElement(HTML.LABEL_ELEM, uiSelectOne);
151         
152         //renderRadio(facesContext,
153         //            uiSelectOne,
154         //            itemStrValue,
155         //            selectItem.getLabel(),
156         //            selectItem.isDisabled(),
157         //            itemStrValue.equals(currentValue), false);
158         //writer.endElement(HTML.LABEL_ELEM);
159 
160         //Render the radio component
161         String itemId = renderRadio(facesContext,
162                 uiSelectOne,
163                 radio,
164                 itemStrValue,
165                 selectItem.isDisabled(),
166                 itemStrValue.equals(currentValue),
167                 false,
168                 index);        
169         
170         //Render the
171         // label element after the input
172         boolean componentDisabled = isDisabled(facesContext, uiSelectOne);
173         boolean itemDisabled = selectItem.isDisabled();
174         boolean disabled = (componentDisabled || itemDisabled);
175 
176         renderLabel(writer, radio, uiSelectOne, itemId, selectItem, disabled);
177     }
178     
179     /**
180      * Renders the input item
181      * @return the 'id' value of the rendered element
182      */
183     protected String renderRadio(FacesContext facesContext,
184                                UIInput uiComponent,
185                                HtmlRadio radio,
186                                String value,
187                                boolean disabled,
188                                boolean checked,
189                                boolean renderId,
190                                Integer itemNum)
191             throws IOException
192     {
193         String clientId = uiComponent.getClientId(facesContext);
194 
195         String itemId = (radio.getId()!=null && !radio.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) ? 
196                 radio.getClientId(facesContext) :
197                 (itemNum == null)? null : clientId + NamingContainer.SEPARATOR_CHAR + itemNum;
198 
199         ResponseWriter writer = facesContext.getResponseWriter();
200 
201         writer.startElement(HTML.INPUT_ELEM, uiComponent);
202 
203         if (itemId != null)
204         {
205             writer.writeAttribute(HTML.ID_ATTR, itemId, null);
206         }
207         else if (renderId) {
208             writer.writeAttribute(HTML.ID_ATTR, clientId, null);
209         }
210 
211         writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_RADIO, null);
212         writer.writeAttribute(HTML.NAME_ATTR, clientId, null);
213 
214         if (disabled) {
215             writer.writeAttribute(HTML.DISABLED_ATTR, HTML.DISABLED_ATTR, null);
216         }
217 
218         if (checked)
219         {
220             writer.writeAttribute(HTML.CHECKED_ATTR, HTML.CHECKED_ATTR, null);
221         }
222 
223         if (value != null)
224         {
225             writer.writeAttribute(HTML.VALUE_ATTR, value, null);
226         }
227 
228         renderHTMLAttributes(writer, radio ,uiComponent, HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
229         
230         if (isDisabled(facesContext, uiComponent))
231         {
232             writer.writeAttribute(org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.DISABLED_ATTR, Boolean.TRUE, null);
233         }
234 
235         writer.endElement(HTML.INPUT_ELEM);
236 
237         return itemId;
238     }
239     
240     public static void renderLabel(ResponseWriter writer, UIComponent radio,
241             UIComponent component, String forClientId, SelectItem item,
242             boolean disabled) throws IOException
243     {
244         writer.startElement(HTML.LABEL_ELEM, component);
245         writer.writeAttribute(HTML.FOR_ATTR, forClientId, null);
246 
247         String labelClass = null;
248 
249         if (disabled)
250         {
251             labelClass = (String) radio.getAttributes().get(
252                     JSFAttr.DISABLED_CLASS_ATTR);
253             if (labelClass == null)
254             {
255                 labelClass = (String) component.getAttributes().get(
256                         JSFAttr.DISABLED_CLASS_ATTR);
257             }
258         }
259         else
260         {
261             labelClass = (String) radio.getAttributes().get(
262                     JSFAttr.ENABLED_CLASS_ATTR);
263             if (labelClass == null)
264             {
265                 labelClass = (String) component.getAttributes().get(
266                         JSFAttr.ENABLED_CLASS_ATTR);
267             }
268         }
269         if (labelClass != null)
270         {
271             writer.writeAttribute("class", labelClass, "labelClass");
272         }
273 
274         if ((item.getLabel() != null) && (item.getLabel().length() > 0))
275         {
276             writer.write(HTML.NBSP_ENTITY);
277             if(item.isEscape())
278             {
279                 writer.writeText(item.getLabel(), null);
280             }
281             else
282             {
283                 writer.write(item.getLabel());
284             }
285         }
286 
287         writer.endElement(HTML.LABEL_ELEM);
288     }
289 
290     private static boolean renderHTMLAttributes(ResponseWriter writer,
291             UIComponent radio, UIComponent selectOne, String[] attributes) throws IOException
292     {
293         boolean somethingDone = false;
294         for (int i = 0, len = attributes.length; i < len; i++)
295         {
296             String attrName = attributes[i];
297             Object value = radio.getAttributes().get(attrName);
298             if (value == null)
299             {
300                 value = selectOne.getAttributes().get(attrName);
301             }
302             if (HtmlRendererUtils.renderHTMLAttribute(writer, attrName, attrName, value ))
303             {
304                 somethingDone = true;
305             }
306         }
307         return somethingDone;
308     }
309 
310     protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
311     {
312         if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
313         {
314             return true;
315         }
316         else
317         {
318             return super.isDisabled(facesContext, uiComponent);
319         }
320     }
321 
322 
323     public void decode(FacesContext facesContext, UIComponent uiComponent)
324     {
325         if (uiComponent instanceof HtmlRadio)
326         {
327             //nothing to decode
328         }
329         else
330         {
331             super.decode(facesContext, uiComponent);
332         }
333     }
334 
335 }