RadioButtonRenderer.java :  » IDE-Netbeans » visualweb.api.designer » com » sun » rave » web » ui » renderer » Java Open Source

Java Open Source » IDE Netbeans » visualweb.api.designer 
visualweb.api.designer » com » sun » rave » web » ui » renderer » RadioButtonRenderer.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */
package com.sun.rave.web.ui.renderer;

import java.io.IOException;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import com.sun.rave.web.ui.component.RadioButton;
import com.sun.rave.web.ui.theme.Theme;
import com.sun.rave.web.ui.theme.ThemeStyles;
import com.sun.rave.web.ui.util.ConversionUtilities;
import com.sun.rave.web.ui.util.MessageUtil;
import com.sun.rave.web.ui.util.ThemeUtilities;

/**
 * <p>
 * The <code>RadioButtonRenderer</code> renders a
 * {@link com.sun.rave.web.ui.component.RadioButton} component.
 * </p>
 * <h3>Encoding</h3>
 * <p>
 * The <code>RadioButtonRenderer</code> renders a <code>RadioButton</code> as:
 * <ul>
 * <li> An INPUT element of type radio for each radio button.
 * </li>
 * <li> An optional image. The component rendered for this feature is obtained
 * from a call to <code>getImageComponent()</code> on the component being
 * rendered. </li>
 * <li> An optional label. The component rendered for this feature is obtained
 * from a call to <code>getLabelComponent()</code> on the component being
 * rendered. </li>
 * </li>
 * </ul>
 * </p>
 * <p>
 * The CSS selectors for the elements and components that comprise a
 * radio button are identified by java
 * constants defined in the {@link ThemeStyles} class.
 * </p>
 * <ul>
 * <li>RADIOBUTTON for the INPUT element</li>
 * <li>RADIOBUTTON_DISABLED for the INPUT element of a disabled radio
 * button</li>
 * <li>RADIOBUTTON_LABEL for label component if a label is rendered</li>
 * <li>RADIOBUTTON_LABEL_DISABLED for a label component of a disabled
 * radio button, if a label is rendered</li>
 * <li>RADIOBUTTON_IMAGE for an image component if an image is rendered</li>
 * <li>RADIOBUTTON_IMAGE_DISABLED for an image component of a disabled 
 * radio button if an image is rendered.</li>
 * </ul>
 * <em>Note that these selectors are appended to any existing selectors
 * that may already exist on the <code>styleClass</code> property of the
 * <code>RadioButton</code> component and the optional image and label
 * components.</em>
 * <p>
 * For more details on the encoding the
 * <code>RadioButton</code> component see the super class
 * {@link com.sun.rave.web.ui.renderer.RbCbRendererBase}
 * </p>
 * <p>
 * <h3>Decoding</h3>
 * <p>
 * If the INPUT element representing a radio button is selected on the
 * the client, the submitted request will contain a request parameter
 * whose name is the value of the name attribute of the selected
 * HTML INPUT element. The value of the request parameter will be the
 * value of the value attribute of the selected HTML INPUT element.
 * </p>
 * <p>
 * The component being decoded is selected if the component's
 * <code>isDisabled</code> and <code>isReadOnly</code> methods
 * return false and:
 * </p>
 * <ul>
 * <li>a request parameter exists that is equal to its <code>name</code>
 * property. If the <code>name</code> property is null, then a
 * request parameter exists that is equal to its <code>clientId</code>
 * property.
 * <li/>
 * </ul>
 * <p>
 * And
 * </p>
 * <ul>
 * <li>the request parameter's value is <code>String.equal</code> to the
 * the component's <code>selectedValue</code> property, after conversion
 * to a <code>String</code>, by calling
 * <code>ConversionUtilities.convertValueToString</code>. If the component
 * was encoded as a boolean control, then the request parameter's value
 * must be equal to the component's <code>clientId</code> property.
 * </li>
 * </ul>
 * <p>
 * If selected, a <code>String[1]</code> array is assigned as the component's
 * submitted value where the single array element is the <code>String</code>
 * version of the <code>selectedValue</code> property or "true" if the
 * component was encoded as a boolean control.<br/>
 * If not selected, a <code>String[0]</code> array is assigned as the
 * component's submitted value or a <code>String[1]</code> array where the
 * single array element is "false" if the component was encoded as a 
 * boolean control.
 * </p>
 * <p>
 * If the component's <code>isDisabled</code> or <code>isReadOnly</code>
 * methods return true no submitted value is assigned to the component,
 * and results in a null submitted value implying the component
 * was not submitted, and the state of the component is unchanged.
 * <p>
 * Since the <code>RadioButtonRenderer</code> only renders a single 
 * <code>RadioButton</code> component it cannot enforce that at least
 * one radio button should be selected among a group of <code>RadioButton</code>
 * components with the same <code>name</code> property.
 * </p>
 * <p>
 * If the <code>RadioButton</code> is selected, the <code>selected<code>
 * property will be the same value as the <code>selectedValue</code>
 * property. If more than one <code>RadioButton</code> component is
 * encoded with the same <code>name</code> property and more than one
 * <code>RadioButton</code>'s is selectred,
 * the last selected <code>RadioButton</code> component that is encoded
 * will be appear as checked in the HTML page. Subsequently during the
 * next submit, only the checked <code>RadioButton</code> component
 * will be selected.
 * </p>
 */
public class RadioButtonRenderer extends RbCbRendererBase {
    

    private final String MSG_COMPONENT_NOT_RADIOBUTTON =
  "RadioButtonRenderer only renders RadioButton components.";

    /**
     * Creates a new instance of RadioButtonRenderer
     */
    public RadioButtonRenderer() {
        super();
    }
    
    /**
     * <p>Decode the <code>RadioButton</code> selection.</p>
     * <p>
     * If the value of the component's <code>name</code> property
     * has been set, the value is used to match a request parameter.
     * If it has not been set the component clientId is used to match
     * a request parameter. If a match is found, and the value of the 
     * of the request parameter matches the <code>String</code> value of the 
     * component's <code>selectedValue</code> property, the
     * radio button is selected. The component's submitted value is
     * assigned a <code>String[1]</code> array where the single array
     * element is the matching parameter value.
     * </p>
     * <p>
     * If no matching request parameter or value is found, an instance of 
     * <code>String[0]</code> is assigned as the submitted value,
     * meaning that this is a component was not selected.
     * </p>
     * <p>
     * If the component was encoded as a boolean control the
     * value of the matching request attribute will be the component's
     * <code>clientId</code> property if selected. If selected the 
     * submitted value is <code>new String[] { "true" }</code>
     * and <code>new String[] { "false" }</code> if not selected.
     * </p>
     * <p>
     * It is the developer's responsibility to ensure the validity of the
     * <code>name</code> property (the name attribute on the
     * INPUT element) by ensuring that it is unique to the radio buttons
     * for a given group within a form.
     * </p>
     *
     * @param context FacesContext for the request we are processing.
     * @param component The <code>RadioButton</code>
     * component to be decoded.
     */
    public void decode(FacesContext context, UIComponent component) {

  // We need to know the last state of the component before decoding
  // this radio button. This disabled check is not to determine
  // if the radio button was disabled on the client.
  // We assume that the disabled state is in the same state as it was
  // when this radio button was last rendered.
  // If the radio button was disabled then it can not have changed on
  // the client. We ignore the case that it might have been
  // enabled in javascript on the client.
  // This allows us to distinguish that no radio button was selected.
  // No radio buttons are selected when "isDisabled || isReadOnly -> false
  // and no request parameters match the name attribute if part of a
  // group or the clientId if a single radio button.
  //
        if (isDisabled(component) || isReadOnly(component)) {
      return;
  }
  // If there is a request parameter that that matches the
  // name property, this component is one of the possible
  // selections. We need to match the value of the parameter to the
  // the component's value to see if this is the selected component.
  //
  RadioButton radioButton = (RadioButton)component;
  String name = radioButton.getName();
  boolean inGroup = name != null;

  // If name is null use the clientId.
  //
  if (name == null) {
      name = component.getClientId(context);
  }

  Map requestParameterMap = context.getExternalContext().
      getRequestParameterMap();

  // The request parameter map contains the INPUT element
  // name attribute value as a parameter. The value is the
  // the "selectedValue" value of the RadioButton component.
  //
  if (requestParameterMap.containsKey(name)) {

      String newValue = (String)requestParameterMap.get(name);

      // We need to discern the case where the radio button
      // is part of a group and it is a boolean radio button.
      // If the radio button is part of a group and it is a
      // boolean radio button then the submitted value contains the
      // value of "component.getClientId()". If 
      // the value was not a unique value within the group
      // of boolean radio buttons, then all will appear selected,
      // since name will be the same for all the radio buttons
      // and the submitted value would always be "true" and then
      // every radio button component in the group would decode
      // as selected. Due to the HTML implementation of radio
      // buttons, only the last radio button will appear selected.
      //
            Object selectedValue = radioButton.getSelectedValue();
      String selectedValueAsString = null;

      if (inGroup && selectedValue instanceof Boolean) {
    selectedValueAsString = component.getClientId(context);
    // Use the toString value of selectedValue even if
    // it is a Boolean control, in case the application
    // wants "FALSE == FALSE" to mean checked.
    //
    if (selectedValueAsString.equals(newValue)) {
        ((UIInput)component).setSubmittedValue(
          new String[] { selectedValue.toString() });
        return;
    }
      } else {
    selectedValueAsString =
        ConversionUtilities.convertValueToString(component,
      selectedValue);
    if (selectedValueAsString.equals(newValue)) {
        ((UIInput)component).setSubmittedValue(
          new String[] { newValue });
        return;
    }
      }
      // Not selected possibly deselected.
      // 
      ((UIInput) component).setSubmittedValue(new String[0]);
  }
  return;
    }

    /**
     * Ensure that the component to be rendered is a RadioButton instance.
     * Actual rendering occurs during <code>renderEnd</code>
     *
     * @param context FacesContext for the request we are processing.
     * @param component UIComponent to be decoded.
     */
    public void renderStart(FacesContext context, UIComponent component,
  ResponseWriter writer)
  throws IOException {

  // Bail out if the component is not a RadioButton component.
  // This message should be logged.
  //
  if (!(component instanceof RadioButton)) {
      throw new
    IllegalArgumentException(MSG_COMPONENT_NOT_RADIOBUTTON);
  }
    }

    /**
     * RadioButtonRenderer renders the entire RadioButton
     * component within the renderEnd method.
     *
     * @param context FacesContext for the request we are processing.
     * @param component UIComponent to be decoded.
     */
    public void renderEnd(FacesContext context, UIComponent component,
  ResponseWriter writer)
  throws IOException {

  Theme theme = ThemeUtilities.getTheme(context);
  renderSelection(context, component, theme, writer, "radio");
        
    }

    /**
     * Return true if the <code>component</code> is selected, false
     * otherwise.
     *
     * @param context FacesContext for the request we are processing.
     * @param component UIComponent to test for selected.
     */
    protected boolean isSelected(FacesContext context, UIComponent component) {
  return ((RadioButton)component).isChecked();
    }

    protected String[] styles = {
  ThemeStyles.RADIOBUTTON,     /* INPUT */
  ThemeStyles.RADIOBUTTON_DISABLED,   /* INPUT_DIS */
  ThemeStyles.RADIOBUTTON_LABEL,    /* LABEL */
  ThemeStyles.RADIOBUTTON_LABEL_DISABLED, /* LABEL_DIS */
  ThemeStyles.RADIOBUTTON_IMAGE,    /* IMAGE */
  ThemeStyles.RADIOBUTTON_IMAGE_DISABLED, /* IMAGE_DIS */
  ThemeStyles.RADIOBUTTON_SPAN,    /* SPAN */
  ThemeStyles.RADIOBUTTON_SPAN_DISABLED  /* SPAN_DIS */
    };

    /**
     * Return the style class name for the structural element indicated
     * by <code>styleCode</code>
     *
     * @param theme The Theme for this request.
     * @param styleCode identifies the style class for the element about
     * to be rendered.
     */
    protected String getStyle(Theme theme, int styleCode) {
  String style = null;
  try {
      style = theme.getStyleClass(styles[styleCode]);
  } catch (Exception e) {
      // Don't care
  }
  return style;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.