Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Form |
|
| 2.8181818181818183;2.818 |
1 | /* | |
2 | * $Source$ | |
3 | * $Revision$ | |
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 | 1 | static Hashtable<String, TempletAdaptor> adaptorCache = new Hashtable<String, TempletAdaptor>(); |
69 | ||
70 | 0 | 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 object the {@link Persistent} to update | |
83 | */ | |
84 | public static void extractFields(ServletTemplateContext context, | |
85 | Persistent object) { | |
86 | 10 | for (Enumeration<Column<?>> c = object.getTable().columns(); c.hasMoreElements();) { |
87 | 63 | Column<?> column = c.nextElement(); |
88 | 63 | String formFieldName = "field_" + column.getName(); |
89 | 63 | String rawString = context.getFormField(formFieldName); |
90 | ||
91 | 63 | String adaptorFieldName = formFieldName + "-adaptor"; |
92 | 63 | String adaptorName = context.getFormField(adaptorFieldName); |
93 | 63 | if (adaptorName != null) { |
94 | 4 | TempletAdaptor adaptor = getAdaptor(adaptorFieldName, adaptorName); |
95 | 4 | column.setRaw(object, adaptor.rawFrom(context, formFieldName)); |
96 | 4 | } else { |
97 | 59 | if (rawString != null) { |
98 | 48 | rawString = rawString.trim(); |
99 | 48 | if (rawString.equals("")) { |
100 | 11 | if (column.getType().getNullable()) |
101 | 11 | column.setRaw(object, null); |
102 | else | |
103 | 0 | column.setRawString(object, ""); |
104 | } else { | |
105 | 37 | column.setRawString(object, rawString); |
106 | } | |
107 | } // else it is not present in form | |
108 | } | |
109 | 63 | } |
110 | 10 | } |
111 | ||
112 | ||
113 | private static TempletAdaptor getAdaptor(String adaptorFieldName, String adaptorName) { | |
114 | 4 | TempletAdaptor adaptor = adaptorCache.get(adaptorName); |
115 | 4 | if(adaptor == null) |
116 | try { | |
117 | 3 | adaptor = (TempletAdaptor)Class.forName(adaptorName).newInstance(); |
118 | 3 | adaptorCache.put(adaptorName, adaptor); |
119 | } | |
120 | 0 | catch (Exception e) { |
121 | 0 | throw new TempletAdaptorConstructionMelatiException( |
122 | adaptorFieldName, adaptorName, e); | |
123 | 3 | } |
124 | ||
125 | 4 | 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 | 2636 | 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 | 2636 | String val = context.getFormField(field); |
154 | 2636 | if (val == null) // field not present in form |
155 | 2569 | return defaultValue; |
156 | 67 | 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 | 0 | String val = getFieldNulled(context, field); |
173 | 0 | 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 | 0 | 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 | 0 | 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 | 280 | 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 | 280 | 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 | 283 | String fenc = UTF8URLEncoder.encode(field); |
254 | 283 | String fenceq = fenc + '='; |
255 | 283 | String fev = fenceq + UTF8URLEncoder.encode(value); |
256 | ||
257 | 283 | if (qs == null || qs.equals("")) return fev; |
258 | ||
259 | int i; | |
260 | 262 | if (qs.startsWith(fenceq)) i = 0; |
261 | else { | |
262 | 261 | i = qs.indexOf('&' + fenceq); |
263 | 261 | if (i == -1) return qs + '&' + fev; |
264 | 45 | ++i; |
265 | } | |
266 | ||
267 | 46 | int a = qs.indexOf('&', i); |
268 | 46 | return qs.substring(0, i) + fev + (a == -1 ? "" : qs.substring(a)); |
269 | } | |
270 | ||
271 | ||
272 | } | |
273 | ||
274 | ||
275 | ||
276 | ||
277 | ||
278 | ||
279 | ||
280 | ||
281 |