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