1 /*
2 * $Source: /usr/cvsroot/melati/melati/src/main/java/org/melati/servlet/Form.java,v $
3 * $Revision: 1.9 $
4 *
5 * Copyright (C) 2000 Tim Joyce
6 *
7 * Part of Melati (http://melati.org), a framework for the rapid
8 * development of clean, maintainable web applications.
9 *
10 * Melati is free software; Permission is granted to copy, distribute
11 * and/or modify this software under the terms either:
12 *
13 * a) the GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the License, or (at your option)
15 * any later version,
16 *
17 * or
18 *
19 * b) any version of the Melati Software License, as published
20 * at http://melati.org
21 *
22 * You should have received a copy of the GNU General Public License and
23 * the Melati Software License along with this program;
24 * if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 * GNU General Public License and visit http://melati.org to obtain the
27 * Melati Software License.
28 *
29 * Feel free to contact the Developers of Melati (http://melati.org),
30 * if you would like to work out a different arrangement than the options
31 * outlined here. It is our intention to allow Melati to be used by as
32 * wide an audience as possible.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * Contact details for copyright holder:
40 *
41 * Tim Joyce <timj At paneris.org>
42 * http://paneris.org/
43 * 68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
44 */
45
46 package org.melati.servlet;
47
48 import java.io.UnsupportedEncodingException;
49 import java.util.Enumeration;
50 import java.util.Hashtable;
51
52
53 import javax.servlet.http.HttpServletRequest;
54
55 import org.melati.poem.Persistent;
56 import org.melati.poem.Column;
57 import org.melati.template.ServletTemplateContext;
58 import org.melati.template.TempletAdaptor;
59 import org.melati.template.TempletAdaptorConstructionMelatiException;
60 import org.melati.util.MelatiBugMelatiException;
61 import org.melati.util.UTF8URLEncoder;
62
63 /**
64 * An object to hold useful static methods for manipulation of a Form in a
65 * {@link ServletTemplateContext}.
66 */
67
68 public final class Form {
69
70 static Hashtable adaptorCache = new Hashtable();
71
72 private Form() {}
73
74 /**
75 * Retrieve updated persistent fields from a context modified in a template.
76 * <p>
77 * The context can specify an adaptor for each field using another HTML
78 * field with name suffix "-adaptor" and value the classname of
79 * a <code>TempletAdaptor</code>.
80 * Hence the templet that renders the field can specify how
81 * the result is parsed.
82 * This is currently used for dates.
83 *
84 * @param context the current {@link ServletTemplateContext} to get values from
85 * @param object the {@link Persistent} to update
86 */
87 public static void extractFields(ServletTemplateContext context,
88 Persistent object) {
89 for (Enumeration c = object.getTable().columns(); c.hasMoreElements();) {
90 Column column = (Column)c.nextElement();
91 String formFieldName = "field_" + column.getName();
92 String rawString = context.getForm(formFieldName);
93
94 String adaptorFieldName = formFieldName + "-adaptor";
95 String adaptorName = context.getForm(adaptorFieldName);
96 if (adaptorName != null) {
97 TempletAdaptor adaptor = getAdaptor(adaptorFieldName, adaptorName);
98 column.setRaw(object, adaptor.rawFrom(context, formFieldName));
99 } else {
100 if (rawString != null) {
101 rawString = rawString.trim();
102 if (rawString.equals("")) {
103 if (column.getType().getNullable())
104 column.setRaw(object, null);
105 else
106 column.setRawString(object, "");
107 } else {
108 String branch;
109 String utf8StringISO = null;
110 String utf8StringUTF8 = null;
111 byte[] stringBytesISO;
112 byte[] stringBytesUTF8;
113 try {
114 stringBytesISO = rawString.getBytes("ISO-8859-1");
115 utf8StringISO = new String(stringBytesISO, "ISO-8859-1");
116 stringBytesUTF8 = rawString.getBytes("UTF-8");
117 utf8StringUTF8 = new String(stringBytesUTF8, "UTF-8");
118
119 if (utf8StringISO.equals(rawString)) {
120 column.setRawString(object, utf8StringISO);
121 branch = "1";
122 } else if (utf8StringUTF8.equals(rawString)) {
123 column.setRawString(object, utf8StringUTF8);
124 branch = "2";
125 } else {
126 column.setRawString(object, rawString);
127 branch = "3";
128 }
129 } catch (UnsupportedEncodingException e) {
130 throw new MelatiBugMelatiException("UTF-8 or ISO-8859-1 not supported", e);
131 }
132 System.err.println("Branch:"+branch+":"+rawString +":"+utf8StringUTF8+":"+utf8StringISO);
133 }
134 }
135 }
136 }
137 }
138
139 /**
140 * Fill in value of a Field from a ServletTemplateContext.
141 *
142 * @param context the current {@link ServletTemplateContext} to get values from
143 * @param fieldName the name of the field to extract
144 * @return the value of the field
145 * @throws TempletAdaptorConstructionMelatiException
146 * if there is a problem, for example with the class name
147 */
148 public static Object extractField(ServletTemplateContext context, String fieldName)
149 throws TempletAdaptorConstructionMelatiException {
150
151 String rawString = context.getForm(fieldName);
152
153 String adaptorFieldName = fieldName + "-adaptor";
154 String adaptorName = context.getForm(adaptorFieldName);
155
156 if (adaptorName != null) {
157 TempletAdaptor adaptor = getAdaptor(adaptorFieldName, adaptorName);
158 return adaptor.rawFrom(context, fieldName);
159 }
160 return rawString;
161 }
162
163
164 private static TempletAdaptor getAdaptor(String adaptorFieldName, String adaptorName) {
165 TempletAdaptor adaptor = (TempletAdaptor)adaptorCache.get(adaptorName);
166 if(adaptor == null)
167 try {
168 adaptor = (TempletAdaptor)Class.forName(adaptorName).newInstance();
169 adaptorCache.put(adaptorName, adaptor);
170 }
171 catch (Exception e) {
172 throw new TempletAdaptorConstructionMelatiException(
173 adaptorFieldName, adaptorName, e);
174 }
175
176 return adaptor;
177 }
178
179 /**
180 * A utility method that gets a value from the Form. It will return
181 * null if the value is "" or not present.
182 *
183 * @param context - a template context
184 * @param field - the name of the field to get
185 *
186 * @return - the value of the field requested
187 */
188 public static String getFieldNulled(ServletTemplateContext context, String field) {
189 return getField(context, field, null);
190 }
191
192
193 /**
194 * A utility method that gets a value from the Form. It will return
195 * the default if the value is "" or not present.
196 *
197 * @param context - a template context
198 * @param field - the name of the field to get
199 * @param defaultValue - the default value if the field is "" or not present
200 *
201 * @return - the value of the field requested
202 */
203 public static String getField(ServletTemplateContext context, String field,
204 String defaultValue) {
205 String val = context.getForm(field);
206 if (val == null) return defaultValue;
207 return val.trim().equals("") ? defaultValue : val;
208 }
209
210 /**
211 * A utility method that gets a value from the Form as an Integer.
212 * It will return null if the value is "" or not present.
213 *
214 * @param context - a template context
215 * @param field - the name of the field to get
216 * @param defaultValue - the default value if the field is "" or not present
217 *
218 * @return - the value of the field requested
219 */
220 public static Integer getIntegerField(ServletTemplateContext context, String field,
221 Integer defaultValue) {
222 String val = getFieldNulled(context, field);
223 return val == null ? defaultValue : new Integer(val);
224 }
225
226 /**
227 * A utility method that gets a value from the Form as an Integer.
228 * It will return null if the value is "" or not present.
229 *
230 * @param context - a template context
231 * @param field - the name of the field to get
232 *
233 * @return - the value of the field requested
234 */
235 public static Integer getIntegerField(ServletTemplateContext context, String field) {
236 return getIntegerField(context, field, null);
237 }
238
239 /**
240 * A utility method that tests whether a field is present in a Form,
241 * returning a Boolean.
242 *
243 * @param context - a template context
244 * @param field - the name of the field to get
245 *
246 * @return - TRUE or FALSE depending if the field is present
247 */
248 public static Boolean getBooleanField(ServletTemplateContext context, String field) {
249 return getFieldNulled(context, field) == null ?
250 Boolean.FALSE : Boolean.TRUE;
251 }
252
253 /**
254 * Modify or add a form parameter setting (query string component) in a URL.
255 *
256 * @param uri A URI
257 * @param query A query string
258 * @param field The parameter's name
259 * @param value The new value for the parameter (unencoded)
260 * @return <TT><I>uri</I>?<I>query</I></TT> with <TT>field=value</TT>.
261 * If there is already a binding for <TT>field</TT> in the
262 * query string it is replaced, not duplicated.
263 */
264
265 public static String sameURLWith(String uri, String query,
266 String field, String value) {
267 return uri + "?" + sameQueryWith(query, field, value);
268 }
269
270 /**
271 * Modify or add a form parameter setting (query string component) in the URL
272 * for a servlet request.
273 *
274 * @param request A servlet request
275 * @param field The parameter's name
276 * @param value The new value for the parameter (unencoded)
277 * @return The request's URL with <TT>field=value</TT>. If there is
278 * already a binding for <TT>field</TT> in the query string
279 * it is replaced, not duplicated. If there is no query
280 * string, one is added.
281 */
282
283 public static String sameURLWith(HttpServletRequest request,
284 String field, String value) {
285 return sameURLWith(request.getRequestURI(), request.getQueryString(),
286 field, value);
287 }
288
289 /**
290 * Modify or add a form parameter setting (query string component) in a query
291 * string.
292 * Note this uses the default encoding.
293 *
294 * @param qs A query string
295 * @param field The parameter's name
296 * @param value The new value for the parameter (unencoded)
297 * @return <TT>qs</TT> with <TT>field=value</TT>.
298 * If there is already a binding for <TT>field</TT> in the
299 * query string it is replaced, not duplicated.
300 */
301 public static String sameQueryWith(String qs, String field, String value) {
302
303 String fenc = UTF8URLEncoder.encode(field);
304 String fenceq = fenc + '=';
305 String fev = fenceq + UTF8URLEncoder.encode(value);
306
307 if (qs == null || qs.equals("")) return fev;
308
309 int i;
310 if (qs.startsWith(fenceq)) i = 0;
311 else {
312 i = qs.indexOf('&' + fenceq);
313 if (i == -1) return qs + '&' + fev;
314 ++i;
315 }
316
317 int a = qs.indexOf('&', i);
318 return qs.substring(0, i) + fev + (a == -1 ? "" : qs.substring(a));
319 }
320
321
322 /**
323 * A utility method that gets a value from the Form. It will return
324 * null if the value is "" or not present.
325 *
326 * @param context - a template context
327 * @param field - the name of the field to get
328 *
329 * @return - the value of the field requested
330 */
331 public static String getFormNulled(ServletTemplateContext context, String field) {
332 return getForm(context, field, null);
333 }
334
335 /**
336 * A utility method that gets a value from the Form. It will return
337 * the default if the value is "" or not present.
338 *
339 * @param context - a template context
340 * @param field - the name of the field to get
341 * @param def - the default value if the field is "" or not present
342 *
343 * @return - the value of the field requested
344 */
345 public static String getForm(ServletTemplateContext context, String field,
346 String def) {
347 String val = context.getForm(field);
348 if (val == null) return def;
349 return val.trim().equals("") ? def : val;
350 }
351
352 }
353
354
355
356
357
358
359
360
361