001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 002// The Molly framework is freely distributable under the terms of an 003// MIT-style license. For details, see the molly pages web site at: 004// http://www.mollypages.org/. Use, modify, have fun ! 005 006package fc.web.forms; 007 008import jakarta.servlet.*; 009import jakarta.servlet.http.*; 010import java.io.*; 011import java.util.*; 012 013import fc.jdbc.*; 014import fc.io.*; 015import fc.util.*; 016 017/** 018Abstracts an HTML choice type such as choicebox or radio. 019Does <b>not</b> abstract a HTML select element for which the 020{@link Select} class should be used. Concrete subclasses 021represent a particular choice element such as {@link 022Checkbox} and {@link Radio} 023 024@author hursh jain 025**/ 026public abstract class Choice extends Field 027{ 028//if this choice object's original state == selected 029private boolean orig_selected; 030//can be null if not specified 031private String value; 032 033static class Data { 034 //the value actually submitted by the browser (could 035 //be 'on', 'ON' etc., or the value for that option (if set) 036 private String submit_value; 037 } 038 039/** 040Creates a new choice object. 041 042@param name the field name 043@param value the value of this choice item (can be null 044 for unspecified) 045@param selected <code>true</code> is this choice is 046 originally selected 047**/ 048protected Choice(String name, String value, boolean selected) 049 { 050 super(name); 051 this.value = value; 052 this.orig_selected = selected; 053 } 054 055public abstract Field.Type getType(); 056 057/** 058Returns the current <b>value</b> of this field. This can be: 059<blockquote> 060<ul> 061 <li><code>null</code>: if no value is currently set which can happen if 062 this field was not selected when the parent form was submitted. 063 Browsers send nothing at all if choice type fields are not selected 064 in an HTML form.</li> 065 <li>the value attribute of this field (if this choice field was 066 created/displayed with a value attribute) or the string "on" (which 067 is sent by browsers if there is no specific value attribute for this 068 choice field). Note, the default value should be treated as case 069 <u>in</u>sensitive, since browsers can send <code>on</code>, <code>ON</code> 070 etc.</li> 071</ul> 072</blockquote> 073**/ 074public String getValue(FormData fd) 075 { 076 Choice.Data data = (Choice.Data) fd.getData(name); 077 078 if (data == null) 079 return null; 080 081 return data.submit_value; 082 } 083 084/** 085Sets the <u>selected or non-selected state</u> for this choice in the 086specified form data. Selected choices are returned by the browser as 087<code>on, ON, oN</code> etc., the value returned is not important as long as 088something is returned. Therefore <i>any non-null value</i> set by this method 089will have the effect of selecting this choice when it is rendered. A <code> 090null</code> value wil unselect this choice. 091 092@param fd a non-null form data object 093@param value any non-null value 094*/ 095public void setValue(FormData fd, String value) 096 { 097 Argcheck.notnull(fd, "specified fd param was null"); 098 099 if (value == null) 100 return; 101 102 Choice.Data data = new Choice.Data(); 103 fd.putData(name, data); 104 data.submit_value = value; 105 } 106 107/** 108Convenience method that sets this choice to be selected/non-selected. 109 110@param fd a non-null form data object 111@param selected true to select this choice, false otherwise 112*/ 113public void setValue(FormData fd, boolean selected) 114 { 115 Argcheck.notnull(fd, "specified fd param was null"); 116 117 if (selected) { 118 Choice.Data data = new Choice.Data(); 119 fd.putData(name, data); 120 //not submit_value = value since value can be null 121 data.submit_value = "on"; 122 } 123 } 124 125/** 126Sets the value for this choice. 127*/ 128public void setValue(String value, boolean selected) 129 { 130 Argcheck.notnull(value, "specified value was null"); 131 132 this.value = value; 133 this.orig_selected = selected; 134 } 135 136/** 137Convenience method that returns the value of this 138field as a Integer. 139 140@throws NumberFormatException if the value could not be 141 returned as in integer. 142*/ 143public int getIntValue(FormData fd) { 144 String value = getValue(fd); 145 if (value != null) 146 value = value.trim(); 147 return Integer.parseInt(value); 148 } 149 150/** 151Convenience method that returns the value of this 152field as a Short. 153 154@throws NumberFormatException if the value could not be 155 returned as a short. 156*/ 157public short getShortValue(FormData fd) { 158 String value = getValue(fd); 159 if (value != null) 160 value = value.trim(); 161 return Short.parseShort(value); 162 } 163 164 165/** 166Convenience method that returns the value of this field as a boolean. 167<u>The returned value will be <code>true</code> if the submitted value is 168"true" or "on" (both case insensitive), else <code>false</code></u> 169*/ 170public boolean getBooleanValue(FormData fd) 171 { 172 String value = getValue(fd); 173 if (value == null) 174 return false; 175 176 if (value.equalsIgnoreCase("on")) 177 value = "true"; 178 179 return Boolean.valueOf(value).booleanValue(); 180 } 181 182//the value actually submitted by the browser (could 183//be 'on', 'ON' etc., or the value for that option if set 184public void setValueFromSubmit(FormData fd, HttpServletRequest req) 185throws SubmitHackedException 186 { 187 String submittedValue = req.getParameter(name); 188 189 //choice was not selected 190 if (submittedValue == null) 191 return; 192 193 Choice.Data data = new Choice.Data(); 194 fd.putData(name, data); 195 196 if (value != null && ! value.equals(submittedValue)) 197 hacklert(req, "submitted value: [" + submittedValue + "] does not equal the value [" + value + "]of this field."); 198 199 data.submit_value = submittedValue; 200 //log.bug(name, "setting data=", submittedValue); 201 } 202 203public void renderImpl(FormData fd, Writer writer) throws IOException 204 { 205 boolean selected = false; 206 207 //no formdata, rendering first time 208 if (fd == null) { 209 selected = this.orig_selected; 210 } 211 else { //submit or initial data 212 String returned_value = getValue(fd); //can be null 213 if (returned_value != null) 214 selected = true; 215 } 216 217 writer.write("<input type='"); 218 writer.write(getType().toString()); 219 writer.write("' name='"); 220 writer.write(name); 221 writer.write("'"); 222 223 if (value != null) { 224 //we always write the orig. value, not the returned 225 //one (since the returned value should be the same 226 //as the original value unless hacked) 227 writer.write(" value='"); 228 writer.write(value); 229 writer.write("'"); 230 } 231 232 if (! enabled || ! isEnabled(fd)) { 233 writer.write(" disabled"); 234 } 235 236 if (selected) { 237 writer.write(" checked"); 238 } 239 240 if (renderStyleTag) { 241 writer.write(" style='"); 242 writer.write(styleTag); 243 writer.write("'"); 244 } 245 246 final int arlen = arbitraryString.size(); 247 for (int n = 0; n < arlen; n++) { 248 writer.write(" "); 249 writer.write(arbitraryString.get(n).toString()); 250 } 251 252 writer.write(">"); 253 writer.write("</input>"); 254 } 255 256 257/** 258@return <code>true</code> if this field is selected, 259 <code>false</code> otherwise 260**/ 261public boolean isFilled(FormData fd) 262 { 263 return getValue(fd) != null; 264 } 265 266/** 267Sets the <b>initial</b> selection status for this field. 268 269@param select <code>true</code> if this field should be selected 270 <code>false</code> otherwise. 271**/ 272public void setSelected(boolean select) { 273 this.orig_selected = select; 274 } 275 276 277public String toString() 278 { 279 return super.toString() + 280 "; Orig. value: [" + value + "]" + 281 "; Orig. selected: [" + orig_selected + "]"; 282 } 283 284}