1 /*
2 * $Source: /usr/cvsroot/melati/melati/src/main/java/org/melati/servlet/Form.java,v $
3 * $Revision: 1.15 $
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.util.Enumeration;
49 import java.util.Hashtable;
50
51
52 import javax.servlet.http.HttpServletRequest;
53
54 import org.melati.poem.Persistent;
55 import org.melati.poem.Column;
56 import org.melati.template.ServletTemplateContext;
57 import org.melati.template.TempletAdaptor;
58 import org.melati.template.TempletAdaptorConstructionMelatiException;
59 import org.melati.util.UTF8URLEncoder;
60
61 /**
62 * An object to hold useful static methods for manipulation of a Form in a
63 * {@link ServletTemplateContext}.
64 */
65
66 public final class Form {
67
68 static Hashtable<String, TempletAdaptor> adaptorCache = new Hashtable<String, TempletAdaptor>();
69
70 private Form() {}
71
72 /**
73 * Retrieve updated persistent fields from a context modified in a template.
74 * <p>
75 * The context can specify an adaptor for each field using another HTML
76 * field with name suffix "-adaptor" and value the classname of
77 * a <code>TempletAdaptor</code>.
78 * Hence the templet that renders the field can specify how the result is parsed.
79 * This is currently used for dates.
80 *
81 * @param context the current {@link ServletTemplateContext} to get values from
82 * @param persistent the {@link Persistent} to update
83 */
84 public static void extractFields(ServletTemplateContext context,
85 Persistent object) {
86 for (Enumeration<Column> c = object.getTable().columns(); c.hasMoreElements();) {
87 Column column = c.nextElement();
88 String formFieldName = "field_" + column.getName();
89 String rawString = context.getFormField(formFieldName);
90
91 String adaptorFieldName = formFieldName + "-adaptor";
92 String adaptorName = context.getFormField(adaptorFieldName);
93 if (adaptorName != null) {
94 TempletAdaptor adaptor = getAdaptor(adaptorFieldName, adaptorName);
95 column.setRaw(object, adaptor.rawFrom(context, formFieldName));
96 } else {
97 if (rawString != null) {
98 rawString = rawString.trim();
99 if (rawString.equals("")) {
100 if (column.getType().getNullable())
101 column.setRaw(object, null);
102 else
103 column.setRawString(object, "");
104 } else {
105 column.setRawString(object, rawString);
106 }
107 } // else it is not present in form
108 }
109 }
110 }
111
112
113 private static TempletAdaptor getAdaptor(String adaptorFieldName, String adaptorName) {
114 TempletAdaptor adaptor = adaptorCache.get(adaptorName);
115 if(adaptor == null)
116 try {
117 adaptor = (TempletAdaptor)Class.forName(adaptorName).newInstance();
118 adaptorCache.put(adaptorName, adaptor);
119 }
120 catch (Exception e) {
121 throw new TempletAdaptorConstructionMelatiException(
122 adaptorFieldName, adaptorName, e);
123 }
124
125 return adaptor;
126 }
127
128 /**
129 * A utility method that gets a value from the Form. It will return
130 * null if the value is "" or not present.
131 *
132 * @param context - a template context
133 * @param field - the name of the field to get
134 *
135 * @return - the value of the field requested
136 */
137 public static String getFieldNulled(ServletTemplateContext context, String field) {
138 return getField(context, field, null);
139 }
140
141 /**
142 * A utility method that gets a value from the Form. It will return
143 * the default if the value is "" or not present.
144 *
145 * @param context - a template context
146 * @param field - the name of the field to get
147 * @param defaultValue - the default value if the field is "" or not present
148 *
149 * @return - the value of the field requested
150 */
151 public static String getField(ServletTemplateContext context, String field,
152 String defaultValue) {
153 String val = context.getFormField(field);
154 if (val == null) // field not present in form
155 return defaultValue;
156 return val.trim().equals("") ? defaultValue : val;
157 }
158
159
160 /**
161 * A utility method that gets a value from the Form as an Integer.
162 * It will return null if the value is "" or not present.
163 *
164 * @param context - a template context
165 * @param field - the name of the field to get
166 * @param defaultValue - the default value if the field is "" or not present
167 *
168 * @return - the value of the field requested
169 */
170 public static Integer getIntegerField(ServletTemplateContext context, String field,
171 Integer defaultValue) {
172 String val = getFieldNulled(context, field);
173 return val == null ? defaultValue : new Integer(val);
174 }
175
176 /**
177 * A utility method that gets a value from the Form as an Integer.
178 * It will return null if the value is "" or not present.
179 *
180 * @param context - a template context
181 * @param field - the name of the field to get
182 *
183 * @return - the value of the field requested
184 */
185 public static Integer getIntegerField(ServletTemplateContext context, String field) {
186 return getIntegerField(context, field, null);
187 }
188
189 /**
190 * A utility method that tests whether a field is present in a Form,
191 * returning a Boolean.
192 *
193 * @param context - a template context
194 * @param field - the name of the field to get
195 *
196 * @return - TRUE or FALSE depending if the field is present
197 */
198 public static Boolean getBooleanField(ServletTemplateContext context, String field) {
199 return getFieldNulled(context, field) == null ?
200 Boolean.FALSE : Boolean.TRUE;
201 }
202
203 /**
204 * Modify or add a form parameter setting (query string component) in a URL.
205 *
206 * @param uri A URI
207 * @param query A query string
208 * @param field The parameter's name
209 * @param value The new value for the parameter (unencoded)
210 * @return <TT><I>uri</I>?<I>query</I></TT> with <TT>field=value</TT>.
211 * If there is already a binding for <TT>field</TT> in the
212 * query string it is replaced, not duplicated.
213 */
214
215 public static String sameURLWith(String uri, String query,
216 String field, String value) {
217 return uri + "?" + sameQueryWith(query, field, value);
218 }
219
220 /**
221 * Modify or add a form parameter setting (query string component) in the URL
222 * for a servlet request.
223 *
224 * @param request A servlet request
225 * @param field The parameter's name
226 * @param value The new value for the parameter (unencoded)
227 * @return The request's URL with <TT>field=value</TT>. If there is
228 * already a binding for <TT>field</TT> in the query string
229 * it is replaced, not duplicated. If there is no query
230 * string, one is added.
231 */
232
233 public static String sameURLWith(HttpServletRequest request,
234 String field, String value) {
235 return sameURLWith(request.getRequestURI(), request.getQueryString(),
236 field, value);
237 }
238
239 /**
240 * Modify or add a form parameter setting (query string component) in a query
241 * string.
242 * Note this uses the default encoding.
243 *
244 * @param qs A query string
245 * @param field The parameter's name
246 * @param value The new value for the parameter (unencoded)
247 * @return <TT>qs</TT> with <TT>field=value</TT>.
248 * If there is already a binding for <TT>field</TT> in the
249 * query string it is replaced, not duplicated.
250 */
251 public static String sameQueryWith(String qs, String field, String value) {
252
253 String fenc = UTF8URLEncoder.encode(field);
254 String fenceq = fenc + '=';
255 String fev = fenceq + UTF8URLEncoder.encode(value);
256
257 if (qs == null || qs.equals("")) return fev;
258
259 int i;
260 if (qs.startsWith(fenceq)) i = 0;
261 else {
262 i = qs.indexOf('&' + fenceq);
263 if (i == -1) return qs + '&' + fev;
264 ++i;
265 }
266
267 int a = qs.indexOf('&', i);
268 return qs.substring(0, i) + fev + (a == -1 ? "" : qs.substring(a));
269 }
270
271
272 }
273
274
275
276
277
278
279
280
281