View Javadoc

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 &quot;-adaptor&quot; 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