001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.component;
042:
043: import java.util.Map;
044:
045: import javax.faces.context.FacesContext;
046: import javax.faces.convert.Converter; // for javadoc
047: import javax.faces.convert.ConverterException;
048: import javax.faces.render.Renderer;
049:
050: import com.sun.rave.web.ui.util.ConversionUtilities;
051:
052: /**
053: * <p>A component that represents a radio button.</p>
054: * <p>
055: * The <code>RadioButton</code> can be used as a single radio button
056: * or one radio button among a group of radio button. A group
057: * of radio button represents a multiple selection list which can have any
058: * number of radio button selected, or none selected. A radio button can
059: * represent a <code>Boolean</code> value, a <code>String</code> value,
060: * or a developer defined <code>Object</code> value.
061: * </p>
062: * <h3>Detecting a selected radio button</h3>
063: * <p>
064: * The <code>RadioButton</code> uses both the <code>selected</code>
065: * and <code>selectedValue</code> properties to pass information about
066: * the radio button's selection status. The <code>selected</code>
067: * property is used to indicate that the radio button is selected.
068: * The <code>selectedValue</code> property is used to pass a data value,
069: * a string by default, for the radio button. A radio button is considered to be
070: * selected when the value of the <code>selected</code> property is equal
071: * to the value of the <code>selectedValue</code> property. A radio button can
072: * be initally selected by assigning the same value
073: * to the <code>selectedValue</code> and the <code> selected</code>
074: * properties. <code>isChecked</code> is called to determine
075: * if this <code>RadioButton</code> is selected.
076: * </p>
077: * <p>If the <code>selectedValue</code> property is not specified or its
078: * value is <code>null</code> then the radio button behaves like a
079: * boolean control. If the radio button is selected, the value of the
080: * <code>selected</code> property is a true <code>Boolean</code>
081: * instance. If the radio button is not selected, the value of the
082: * <code>selected</code> property will be a false <code>Boolean</code>
083: * instance.
084: * </p>
085: * <p> <em>Note that a value binding expression that evaluates to a
086: * primitive boolean value can be assigned to the <code>selected</code>
087: * property. Proper type coercion from <code>Boolean</code> to
088: * <code>boolean</code> occurs.</em>
089: * </p>
090: * <p>
091: * When a radio button is part of a group, the selected radio
092: * button is maintained as a request attribute in the
093: * <code>RequestMap</code>. The name of the attribute is
094: * the value of the radio button's <code>name</code> property.
095: * The request attribute value is the
096: * value of the <code>selectedValue</code> property of the
097: * selected radio button.
098: * The <code>selected</code> property
099: * of the selected radio button within the group, will also contain the
100: * value of the <code>selectedValue</code> property of the
101: * respective selected radio button. If no radio buttons are selected,
102: * no request attribute is created, however at least one radio button
103: * must be selected.
104: * </p>
105: * <p><em>
106: * Note that the <code>RadioButton</code> does not enforce the
107: * requirement that at least one radio button must be selected.
108: * The application should ensure that this requirement is met.
109: * </em></p>
110: * <h3>Using a <code>radio button</code> tag as a boolean control</h3>
111: * <p>
112: * If the <code>selectedValue</code> property is not specified or its
113: * value is <code>null</code> then the radio button behaves like a
114: * boolean control.
115: * </p>
116: * <p>
117: * To use the <code>RadioButton</code> as a boolean control, do not
118: * specify a value for the <code>selectedValue</code> property. The
119: * radio button is selected if the <code>selected</code> property is not
120: * null and has the value of a Boolean instance with a <code>true</code>
121: * value. If the radio button is not selected, then the value of the
122: * <code>selected</code> property is a false <code>Boolean</code> instance.
123: * </p>
124: * <p><em>Note that using a boolean radio button in a group and
125: * referencing the request property for the selected radio button is not
126: * useful, since the value of the request property will be an
127: * indistinguishable <code>true</code> value.</em>
128: * </p>
129: * <h3>Using a <code>RadioButton</code> to represent a developer defined
130: * value</h3>
131: * <p> The <code>selectedValue</code> property can be assigned a
132: * developer defined object value to represent the value of a selected
133: * radio button. If the radio button is selected, the value of the
134: * <code>selected</code> property is assigned the value of the
135: * <code>selectedValue</code> property.
136: * </p>
137: * <p>
138: * If the value of the <code>selectedValue</code> property is a
139: * developer defined object, a <code>Converter</code> must be registered
140: * to convert to and from a <code>String</code> value.<br>
141: * In addition the object must support an
142: * <code>equals</code> method that returns <code>true</code> when the
143: * value of the <code>selectedValue</code> property is compared to
144: * the <code>selected</code> property value in order to detect a
145: * selected radio button.
146: * </p>
147: * <h3>Using a <code>RadioButton</code> as one control in a group</h3>
148: * <p>
149: * The <code>name</code> property determines whether a
150: * radio button is part of a group. A radio button is treated as part of a group
151: * of radio buttons if the <code>name</code> property of the radio button is
152: * assigned a value equal to the <code>name</code> property of the other
153: * radio buttons in the group. In other words, all radio button of a
154: * group have the same <code>name</code> property value. The group behaves
155: * like a single selection list, where only one radio button
156: * can be selected. The value of the name property must
157: * be unique within the scope of the Form parent containing the
158: * radio buttons.
159: * </p>
160: * <h3>Facets</h3>
161: * <p>
162: * The following facets are supported:
163: * </p>
164: * <ul>
165: * <li><em>image</em> If the image facet exists, it replaces the
166: * {@link com.sun.rave.web.ui.component.ImageComponent} subcompoent
167: * normally created for the image associated with the radio button,
168: * if the <code>imageURL</code> property is not null.</li>
169: * <li><em>label</em> If the label facet exists, it replaces the
170: * {@link com.sun.rave.web.ui.component.Label} subcomponent normally
171: * created for the label associated with the radio button, if the
172: * label property is not null.</li>
173: * </ul>
174: * <p>
175: * Add an image or label facet to the <code>RadioButton</code> if more
176: * control over the properties of the subcomponents is needed.
177: * </p>
178: * <p>
179: * <em>Note that if a facet is exists, <code>RadioButton</code> properties
180: * that would normally be assigned to the created subcomponent, will
181: * not be assigned to the facet</em>
182: * </p>
183: * <p>
184: * <em>Note that unexpected layout of the <code>RadioButton</code> may occur
185: * if the component specified by the facet is not a
186: * {@link com.sun.rave.web.ui.component.ImageComponent} for the image facet or
187: * {@link com.sun.rave.web.ui.component.Label} for the label facet.</em>
188: * </p>
189: * <h3>ImageComponent and Label subcomponents</h3>
190: * <p>
191: * An image and a label may be associated with the
192: * <code>RadioButton</code>.<br/>
193: * If the <code>imageURL</code> property is not null and an image facet
194: * does not exist then a {@link com.sun.rave.web.ui.component.ImageComponent}
195: * component is created.<br/>
196: * If the <code>label</code> property is not null and a label facet does not
197: * exist then a {@link com.sun.rave.web.ui.component.Label} component is
198: * created.
199: * </p>
200: * <p>
201: * The following <code>RadioButton</code> properties are assigned to
202: * the subcomponents only if a facet does not exist.<br/>
203: * For the {@link com.sun.rave.web.ui.component.ImageComponent} subcomponent
204: * <ul>this.getId() + "_image" is assigned to the <code>id</code> property.</li>
205: * <li>this.getImageURL() is assigned to the <code>url</code> property.</li>
206: * <li>this.getToolTip() is assigned to the <code>toolTip</code> property.</li>
207: * <li>this.getToolTip() is assigned to the <code>alt</code> property.</li>
208: * <li>this.isVisible() is assigned to the <code>visible</code> property.</li>
209: * <li>this.isRendered() is assigned to the <code>renderer</code> property.</li>
210: * </ul>
211: * </p>
212: * <p>
213: * For the {@link com.sun.rave.web.ui.component.Label} subcomponent
214: * <ul>
215: * <li>this.getId() + "_label" is assigned to the <code>id</code>
216: * property.</li>
217: * <li>this.getClientId() is assigned to the <code>for</code>
218: * property.</li>
219: * <li>this.getLabel() is assigned to the <code>text</code> property.</li>
220: * <li>this.getLabelLevel is assigned to the <code>labelLevel</code> property.</li>
221: * <li>this.getToolTip is assigned to the <code>toolTip</code> property.</li>
222: * <li>this.isVisible is assigned to the <code>visible</code> property.</li>
223: * <li>this.isRendered is assigned to the <code>renderer</code> property.</li>
224: * </ul>
225: * </p>
226: * <em>Note that if a value binding exists for one of the
227: * <code>RadioButton</code> properties mentioned above, the value binding is
228: * set on the subcomponent for that property.</em>
229: * </p>
230: */
231: public class RadioButton extends RadioButtonBase {
232:
233: /**
234: * Construct a <code>RadioButton</code> instance.
235: */
236: public RadioButton() {
237: super ();
238: setMultiple(false);
239: }
240:
241: /**
242: * Return the value of the <code>selectedValue</code> property
243: * of the selected radio button in the group of radio buttons
244: * identified by the <code>name</code> parameter.
245: * A <code>RadioButton</code> is one of a group of radio buttons
246: * if more than on radio button has the same value for the
247: * <code>name</code> property.<br/>
248: * When one of the radio buttons among that group is selected,
249: * the value of its <code>selectedValue</code> property
250: * is maintained in a request attribute identified by the value
251: * of its <code>name</code> property.
252: *
253: * @param name the value a RadioButton name property.
254: */
255: public static Object getSelected(String name) {
256:
257: Map rm = FacesContext.getCurrentInstance().getExternalContext()
258: .getRequestMap();
259:
260: if (name != null) {
261: return rm.get(name);
262: } else {
263: return null;
264: }
265: }
266:
267: /**
268: * <p>Update the request parameter that holds the value of the
269: * <code>selectedValue</code> property of the selected radio button.
270: * </p>
271: * If the <code>name</code> property has been set
272: * a request attribute is created.
273: * The value of the <code>name</code> property will
274: * be used for the request attribute name and the value of the request
275: * attribute will be the value of the
276: * <code>selectedValue</code> property.
277: * <p>
278: * The request attribute described above is available during
279: * a <code>ValueChangeEvent</code>.
280: * </p>
281: *
282: * @param context The context of this request.
283: */
284: public void validate(FacesContext context) {
285:
286: super .validate(context);
287:
288: if (!(isValid() && isChecked())) {
289: return;
290: }
291:
292: String groupName = getName();
293: if (groupName == null) {
294: return;
295: }
296:
297: addToRequestMap(context, groupName);
298: }
299:
300: protected void addToRequestMap(FacesContext context,
301: String groupName) {
302:
303: Map requestMap = context.getExternalContext().getRequestMap();
304: requestMap.put(groupName, getValue());
305: }
306: }
|