Form.java
/*
* $Source$
* $Revision$
*
* Copyright (C) 2000 Tim Joyce
*
* Part of Melati (http://melati.org), a framework for the rapid
* development of clean, maintainable web applications.
*
* Melati is free software; Permission is granted to copy, distribute
* and/or modify this software under the terms either:
*
* a) the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version,
*
* or
*
* b) any version of the Melati Software License, as published
* at http://melati.org
*
* You should have received a copy of the GNU General Public License and
* the Melati Software License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
* GNU General Public License and visit http://melati.org to obtain the
* Melati Software License.
*
* Feel free to contact the Developers of Melati (http://melati.org),
* if you would like to work out a different arrangement than the options
* outlined here. It is our intention to allow Melati to be used by as
* wide an audience as possible.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact details for copyright holder:
*
* Tim Joyce <timj At paneris.org>
* http://paneris.org/
* 68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
*/
package org.melati.servlet;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.http.HttpServletRequest;
import org.melati.poem.Persistent;
import org.melati.poem.Column;
import org.melati.template.ServletTemplateContext;
import org.melati.template.TempletAdaptor;
import org.melati.template.TempletAdaptorConstructionMelatiException;
import org.melati.util.UTF8URLEncoder;
/**
* An object to hold useful static methods for manipulation of a Form in a
* {@link ServletTemplateContext}.
*/
public final class Form {
static Hashtable<String, TempletAdaptor> adaptorCache = new Hashtable<String, TempletAdaptor>();
private Form() {}
/**
* Retrieve updated persistent fields from a context modified in a template.
* <p>
* The context can specify an adaptor for each field using another HTML
* field with name suffix "-adaptor" and value the classname of
* a <code>TempletAdaptor</code>.
* Hence the templet that renders the field can specify how the result is parsed.
* This is currently used for dates.
*
* @param context the current {@link ServletTemplateContext} to get values from
* @param object the {@link Persistent} to update
*/
public static void extractFields(ServletTemplateContext context,
Persistent object) {
for (Enumeration<Column<?>> c = object.getTable().columns(); c.hasMoreElements();) {
Column<?> column = c.nextElement();
String formFieldName = "field_" + column.getName();
String rawString = context.getFormField(formFieldName);
String adaptorFieldName = formFieldName + "-adaptor";
String adaptorName = context.getFormField(adaptorFieldName);
if (adaptorName != null) {
TempletAdaptor adaptor = getAdaptor(adaptorFieldName, adaptorName);
column.setRaw(object, adaptor.rawFrom(context, formFieldName));
} else {
if (rawString != null) {
rawString = rawString.trim();
if (rawString.equals("")) {
if (column.getType().getNullable())
column.setRaw(object, null);
else
column.setRawString(object, "");
} else {
column.setRawString(object, rawString);
}
} // else it is not present in form
}
}
}
private static TempletAdaptor getAdaptor(String adaptorFieldName, String adaptorName) {
TempletAdaptor adaptor = adaptorCache.get(adaptorName);
if(adaptor == null)
try {
adaptor = (TempletAdaptor)Class.forName(adaptorName).newInstance();
adaptorCache.put(adaptorName, adaptor);
}
catch (Exception e) {
throw new TempletAdaptorConstructionMelatiException(
adaptorFieldName, adaptorName, e);
}
return adaptor;
}
/**
* A utility method that gets a value from the Form. It will return
* null if the value is "" or not present.
*
* @param context - a template context
* @param field - the name of the field to get
*
* @return - the value of the field requested
*/
public static String getFieldNulled(ServletTemplateContext context, String field) {
return getField(context, field, null);
}
/**
* A utility method that gets a value from the Form. It will return
* the default if the value is "" or not present.
*
* @param context - a template context
* @param field - the name of the field to get
* @param defaultValue - the default value if the field is "" or not present
*
* @return - the value of the field requested
*/
public static String getField(ServletTemplateContext context, String field,
String defaultValue) {
String val = context.getFormField(field);
if (val == null) // field not present in form
return defaultValue;
return val.trim().equals("") ? defaultValue : val;
}
/**
* A utility method that gets a value from the Form as an Integer.
* It will return null if the value is "" or not present.
*
* @param context - a template context
* @param field - the name of the field to get
* @param defaultValue - the default value if the field is "" or not present
*
* @return - the value of the field requested
*/
public static Integer getIntegerField(ServletTemplateContext context, String field,
Integer defaultValue) {
String val = getFieldNulled(context, field);
return val == null ? defaultValue : new Integer(val);
}
/**
* A utility method that gets a value from the Form as an Integer.
* It will return null if the value is "" or not present.
*
* @param context - a template context
* @param field - the name of the field to get
*
* @return - the value of the field requested
*/
public static Integer getIntegerField(ServletTemplateContext context, String field) {
return getIntegerField(context, field, null);
}
/**
* A utility method that tests whether a field is present in a Form,
* returning a Boolean.
*
* @param context - a template context
* @param field - the name of the field to get
*
* @return - TRUE or FALSE depending if the field is present
*/
public static Boolean getBooleanField(ServletTemplateContext context, String field) {
return getFieldNulled(context, field) == null ?
Boolean.FALSE : Boolean.TRUE;
}
/**
* Modify or add a form parameter setting (query string component) in a URL.
*
* @param uri A URI
* @param query A query string
* @param field The parameter's name
* @param value The new value for the parameter (unencoded)
* @return <TT><I>uri</I>?<I>query</I></TT> with <TT>field=value</TT>.
* If there is already a binding for <TT>field</TT> in the
* query string it is replaced, not duplicated.
*/
public static String sameURLWith(String uri, String query,
String field, String value) {
return uri + "?" + sameQueryWith(query, field, value);
}
/**
* Modify or add a form parameter setting (query string component) in the URL
* for a servlet request.
*
* @param request A servlet request
* @param field The parameter's name
* @param value The new value for the parameter (unencoded)
* @return The request's URL with <TT>field=value</TT>. If there is
* already a binding for <TT>field</TT> in the query string
* it is replaced, not duplicated. If there is no query
* string, one is added.
*/
public static String sameURLWith(HttpServletRequest request,
String field, String value) {
return sameURLWith(request.getRequestURI(), request.getQueryString(),
field, value);
}
/**
* Modify or add a form parameter setting (query string component) in a query
* string.
* Note this uses the default encoding.
*
* @param qs A query string
* @param field The parameter's name
* @param value The new value for the parameter (unencoded)
* @return <TT>qs</TT> with <TT>field=value</TT>.
* If there is already a binding for <TT>field</TT> in the
* query string it is replaced, not duplicated.
*/
public static String sameQueryWith(String qs, String field, String value) {
String fenc = UTF8URLEncoder.encode(field);
String fenceq = fenc + '=';
String fev = fenceq + UTF8URLEncoder.encode(value);
if (qs == null || qs.equals("")) return fev;
int i;
if (qs.startsWith(fenceq)) i = 0;
else {
i = qs.indexOf('&' + fenceq);
if (i == -1) return qs + '&' + fev;
++i;
}
int a = qs.indexOf('&', i);
return qs.substring(0, i) + fev + (a == -1 ? "" : qs.substring(a));
}
}