All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.faces.convert.DateTimeConverter Maven / Gradle / Ivy

Go to download

This is the master POM file for Sun's Implementation of the JSF 1.2 Specification.

There is a newer version: 2.1
Show newest version
/*
 * $Id: DateTimeConverter.java,v 1.34.4.2 2008/12/03 23:29:29 rlubke Exp $
 */

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package javax.faces.convert;


import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;


/**
 * 

{@link Converter} implementation for java.util.Date * values.

*

*

The getAsObject() method parses a String into a * java.util.Date, according to the following algorithm:

*
    *
  • If the specified String is null, return * a null. Otherwise, trim leading and trailing * whitespace before proceeding.
  • *
  • If the specified String - after trimming - has a zero length, * return null.
  • *
  • If the locale property is not null, * use that Locale for managing parsing. Otherwise, use the * Locale from the UIViewRoot.
  • *
  • If a pattern has been specified, its syntax must conform * the rules specified by java.text.SimpleDateFormat. Such * a pattern will be used to parse, and the type, * dateStyle, and timeStyle properties * will be ignored.
  • *
  • If a pattern has not been specified, parsing will be based * on the type property, which expects a date value, a time * value, or both. Any date and time values included will be parsed in * accordance to the styles specified by dateStyle and * timeStyle, respectively.
  • *
  • If a timezone has been specified, it must be passed * to the underlying DateFormat instance. Otherwise * the "GMT" timezone is used.
  • *
  • In all cases, parsing must be non-lenient; the given string must * strictly adhere to the parsing format.
  • *
*

*

The getAsString() method expects a value of type * java.util.Date (or a subclass), and creates a formatted * String according to the following algorithm:

*
    *
  • If the specified value is null, return a zero-length String.
  • *
  • If the specified value is a String, return it unmodified.
  • *
  • If the locale property is not null, * use that Locale for managing formatting. Otherwise, use the * Locale from the UIViewRoot.
  • *
  • If a timezone has been specified, it must be passed * to the underlying DateFormat instance. Otherwise * the "GMT" timezone is used.
  • *
  • If a pattern has been specified, its syntax must conform * the rules specified by java.text.SimpleDateFormat. Such * a pattern will be used to format, and the type, * dateStyle, and timeStyle properties * will be ignored.
  • *
  • If a pattern has not been specified, formatting will be * based on the type property, which includes a date value, * a time value, or both into the formatted String. Any date and time * values included will be formatted in accordance to the styles specified * by dateStyle and timeStyle, respectively.
  • *
*/ public class DateTimeConverter implements Converter, StateHolder { // ------------------------------------------------------ Manifest Constants /** *

The standard converter id for this converter.

*/ public static final String CONVERTER_ID = "javax.faces.DateTime"; /** *

The message identifier of the {@link javax.faces.application.FacesMessage} to be created if * the conversion to Date fails. The message format * string for this message may optionally include the following * placeholders: *

    *
  • {0} replaced by the unconverted value.
  • *
  • {1} replaced by an example value.
  • *
  • {2} replaced by a String whose value * is the label of the input component that produced this message.
  • *

*/ public static final String DATE_ID = "javax.faces.converter.DateTimeConverter.DATE"; /** *

The message identifier of the {@link javax.faces.application.FacesMessage} to be created if * the conversion to Time fails. The message format * string for this message may optionally include the following * placeholders: *

    *
  • {0} replaced by the unconverted value.
  • *
  • {1} replaced by an example value.
  • *
  • {2} replaced by a String whose value * is the label of the input component that produced this message.
  • *

*/ public static final String TIME_ID = "javax.faces.converter.DateTimeConverter.TIME"; /** *

The message identifier of the {@link javax.faces.application.FacesMessage} to be created if * the conversion to DateTime fails. The message format * string for this message may optionally include the following * placeholders: *

    *
  • {0} replaced by the unconverted value.
  • *
  • {1} replaced by an example value.
  • *
  • {2} replaced by a String whose value * is the label of the input component that produced this message.
  • *

*/ public static final String DATETIME_ID = "javax.faces.converter.DateTimeConverter.DATETIME"; /** *

The message identifier of the {@link javax.faces.application.FacesMessage} to be created if * the conversion of the DateTime value to * String fails. The message format string for this message * may optionally include the following placeholders: *

    *
  • {0} relaced by the unconverted value.
  • *
  • {1} replaced by a String whose value * is the label of the input component that produced this message.
  • *

*/ public static final String STRING_ID = "javax.faces.converter.STRING"; private static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("GMT"); // ------------------------------------------------------ Instance Variables private String dateStyle = "default"; private Locale locale = null; private String pattern = null; private String timeStyle = "default"; private TimeZone timeZone = DEFAULT_TIME_ZONE; private String type = "date"; // -------------------------------------------------------------- Properties /** *

Return the style to be used to format or parse dates. If not set, * the default value, default, is returned.

*/ public String getDateStyle() { return (this.dateStyle); } /** *

Set the style to be used to format or parse dates. Valid values * are default, short, medium, * long, and full. * An invalid value will cause a {@link ConverterException} when * getAsObject() or getAsString() is called.

* * @param dateStyle The new style code */ public void setDateStyle(String dateStyle) { this.dateStyle = dateStyle; } /** *

Return the Locale to be used when parsing or formatting * dates and times. If not explicitly set, the Locale stored * in the {@link javax.faces.component.UIViewRoot} for the current * request is returned.

*/ public Locale getLocale() { if (this.locale == null) { this.locale = getLocale(FacesContext.getCurrentInstance()); } return (this.locale); } /** *

Set the Locale to be used when parsing or formatting * dates and times. If set to null, the Locale * stored in the {@link javax.faces.component.UIViewRoot} for the current * request will be utilized.

* * @param locale The new Locale (or null) */ public void setLocale(Locale locale) { this.locale = locale; } /** *

Return the format pattern to be used when formatting and * parsing dates and times.

*/ public String getPattern() { return (this.pattern); } /** *

Set the format pattern to be used when formatting and parsing * dates and times. Valid values are those supported by * java.text.SimpleDateFormat. * An invalid value will cause a {@link ConverterException} when * getAsObject() or getAsString() is called.

* * @param pattern The new format pattern */ public void setPattern(String pattern) { this.pattern = pattern; } /** *

Return the style to be used to format or parse times. If not set, * the default value, default, is returned.

*/ public String getTimeStyle() { return (this.timeStyle); } /** *

Set the style to be used to format or parse times. Valid values * are default, short, medium, * long, and full. * An invalid value will cause a {@link ConverterException} when * getAsObject() or getAsString() is called.

* * @param timeStyle The new style code */ public void setTimeStyle(String timeStyle) { this.timeStyle = timeStyle; } /** *

Return the TimeZone used to interpret a time value. * If not explicitly set, the default time zone of GMT * returned.

*/ public TimeZone getTimeZone() { return (this.timeZone); } /** *

Set the TimeZone used to interpret a time value.

* * @param timeZone The new time zone */ public void setTimeZone(TimeZone timeZone) { this.timeZone = timeZone; } /** *

Return the type of value to be formatted or parsed. * If not explicitly set, the default type, date * is returned.

*/ public String getType() { return (this.type); } /** *

Set the type of value to be formatted or parsed. * Valid values are both, date, or * time. * An invalid value will cause a {@link ConverterException} when * getAsObject() or getAsString() is called.

* * @param type The new date style */ public void setType(String type) { this.type = type; } // ------------------------------------------------------- Converter Methods /** * @throws ConverterException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ public Object getAsObject(FacesContext context, UIComponent component, String value) { if (context == null || component == null) { throw new NullPointerException(); } Object returnValue = null; DateFormat parser = null; try { // If the specified value is null or zero-length, return null if (value == null) { return (null); } value = value.trim(); if (value.length() < 1) { return (null); } // Identify the Locale to use for parsing Locale locale = getLocale(context); // Create and configure the parser to be used parser = getDateFormat(locale); if (null != timeZone) { parser.setTimeZone(timeZone); } // Perform the requested parsing returnValue = parser.parse(value); } catch (ParseException e) { if ("date".equals(type)) { throw new ConverterException(MessageFactory.getMessage( context, DATE_ID, value, parser.format(new Date(System.currentTimeMillis())), MessageFactory.getLabel(context, component)), e); } else if ("time".equals(type)) { throw new ConverterException(MessageFactory.getMessage( context, TIME_ID, value, parser.format(new Date(System.currentTimeMillis())), MessageFactory.getLabel(context, component)), e); } else if ("both".equals(type)) { throw new ConverterException(MessageFactory.getMessage( context, DATETIME_ID, value, parser.format(new Date(System.currentTimeMillis())), MessageFactory.getLabel(context, component)), e); } } catch (Exception e) { throw new ConverterException(e); } return returnValue; } /** * @throws ConverterException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ public String getAsString(FacesContext context, UIComponent component, Object value) { if (context == null || component == null) { throw new NullPointerException(); } try { // If the specified value is null, return a zero-length String if (value == null) { return ""; } // If the incoming value is still a string, play nice // and return the value unmodified if (value instanceof String) { return (String) value; } // Identify the Locale to use for formatting Locale locale = getLocale(context); // Create and configure the formatter to be used DateFormat formatter = getDateFormat(locale); if (null != timeZone) { formatter.setTimeZone(timeZone); } // Perform the requested formatting return (formatter.format(value)); } catch (ConverterException e) { throw new ConverterException(MessageFactory.getMessage( context, STRING_ID, value, MessageFactory.getLabel(context, component)), e); } catch (Exception e) { throw new ConverterException(MessageFactory.getMessage( context, STRING_ID, value, MessageFactory.getLabel(context, component)), e); } } // --------------------------------------------------------- Private Methods /** *

Return a DateFormat instance to use for formatting * and parsing in this {@link Converter}.

* * @param locale The Locale used to select formatting * and parsing conventions * @throws ConverterException if no instance can be created */ private DateFormat getDateFormat(Locale locale) { // PENDING(craigmcc) - Implement pooling if needed for performance? if (pattern == null && type == null) { throw new IllegalArgumentException("Either pattern or type must" + " be specified."); } DateFormat df; if (pattern != null) { df = new SimpleDateFormat(pattern, locale); } else if (type.equals("both")) { df = DateFormat.getDateTimeInstance (getStyle(dateStyle), getStyle(timeStyle), locale); } else if (type.equals("date")) { df = DateFormat.getDateInstance(getStyle(dateStyle), locale); } else if (type.equals("time")) { df = DateFormat.getTimeInstance(getStyle(timeStyle), locale); } else { // PENDING(craigmcc) - i18n throw new IllegalArgumentException("Invalid type: " + type); } df.setLenient(false); return (df); } /** *

Return the Locale we will use for localizing our * formatting and parsing processing.

* * @param context The {@link FacesContext} for the current request */ private Locale getLocale(FacesContext context) { // PENDING(craigmcc) - JSTL localization context? Locale locale = this.locale; if (locale == null) { locale = context.getViewRoot().getLocale(); } return (locale); } /** *

Return the style constant for the specified style name.

* * @param name Name of the style for which to return a constant * @throws ConverterException if the style name is not valid */ private static int getStyle(String name) { if ("default".equals(name)) { return (DateFormat.DEFAULT); } else if ("short".equals(name)) { return (DateFormat.SHORT); } else if ("medium".equals(name)) { return (DateFormat.MEDIUM); } else if ("long".equals(name)) { return (DateFormat.LONG); } else if ("full".equals(name)) { return (DateFormat.FULL); } else { // PENDING(craigmcc) - i18n throw new ConverterException("Invalid style '" + name + '\''); } } // ----------------------------------------------------- StateHolder Methods public Object saveState(FacesContext context) { Object values[] = new Object[6]; values[0] = dateStyle; values[1] = locale; values[2] = pattern; values[3] = timeStyle; values[4] = timeZone; values[5] = type; return (values); } public void restoreState(FacesContext context, Object state) { Object values[] = (Object[]) state; dateStyle = (String) values[0]; locale = (Locale) values[1]; pattern = (String) values[2]; timeStyle = (String) values[3]; timeZone = (TimeZone) values[4]; type = (String) values[5]; } private boolean transientFlag = false; public boolean isTransient() { return (transientFlag); } public void setTransient(boolean transientFlag) { this.transientFlag = transientFlag; } }