blob: 321bca89a795cf3e738da752adaafcea1ba7ff2c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.woody.datatype.convertor;
import java.util.Locale;
import java.util.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* A Convertor for {@link java.util.Date Date} objects backed by the
* {@link java.text.SimpleDateFormat SimpleDateFormat} class.
*
* <p>It can be configured to use one of three <strong>variants</strong>: date,
* time or datetime and one of four <strong>styles</strong>: long, full, medium or short.
*
* <p>Alternatively, a <strong>formatting pattern</strong> can be used. This can either be a locale-dependent
* or locale-independent formatting pattern. When looking up a formatting pattern, a mechansim
* similar to resource bundle lookup is used. Suppose the locale is nl-BE, then first a formatting
* pattern for nl-BE will be sought, then one for nl, and if that is not
* found, finally the locale-independent formatting pattern will be used.
*
* <p><strong>NOTE:</strong> the earlier statement about the fact that this class uses java.text.SimpleDateFormat
* is not entirely correct. In fact, it uses a small wrapper class that will either delegate to
* java.text.SimpleDateFormat or com.ibm.icu.text.SimpleDateFormat. The com.ibm version will automatically
* be used if it is present on the classpath, otherwise the java.text version will be used.
*
* @version CVS $Id$
*/
public class FormattingDateConvertor implements Convertor {
/** See {@link #setStyle}. */
private int style;
/** See {@link #setVariant}. */
private int variant;
/** Locale-specific formatting patterns. */
private LocaleMap localizedPatterns;
/** Non-locale specific formatting pattern. */
private String nonLocalizedPattern;
public static final int DATE = 1;
public static final int TIME = 2;
public static final int DATE_TIME = 3;
public FormattingDateConvertor() {
this.style = java.text.DateFormat.SHORT;
this.variant = DATE;
this.localizedPatterns = new LocaleMap();
}
public Object convertFromString(String value, Locale locale, Convertor.FormatCache formatCache) {
DateFormat dateFormat = getDateFormat(locale, formatCache);
try {
return dateFormat.parse(value);
} catch (ParseException e) {
return null;
}
}
public String convertToString(Object value, Locale locale, Convertor.FormatCache formatCache) {
DateFormat dateFormat = getDateFormat(locale, formatCache);
return dateFormat.format((Date)value);
}
private final DateFormat getDateFormat(Locale locale, Convertor.FormatCache formatCache) {
DateFormat dateFormat = null;
if (formatCache != null)
dateFormat = (DateFormat)formatCache.get();
if (dateFormat == null) {
dateFormat = getDateFormat(locale);
if (formatCache != null)
formatCache.store(dateFormat);
}
return dateFormat;
}
protected DateFormat getDateFormat(Locale locale) {
SimpleDateFormat dateFormat = null;
switch (variant) {
case DATE:
dateFormat = (SimpleDateFormat)DateFormat.getDateInstance(style, locale);
break;
case TIME:
dateFormat = (SimpleDateFormat)DateFormat.getTimeInstance(style, locale);
break;
case DATE_TIME:
dateFormat = (SimpleDateFormat)DateFormat.getDateTimeInstance(style, style, locale);
break;
}
String pattern = (String)localizedPatterns.get(locale);
if (pattern != null)
// Note: this was previously using applyLocalizedPattern() which allows to use
// a locale-specific pattern syntax, e.g. in french "j" (jour) for "d" and
// "a" (annee) for "y". But the localized pattern syntax is very little known and thus
// led to some weird pattern syntax error messages.
dateFormat.applyPattern(pattern);
else if (nonLocalizedPattern != null)
dateFormat.applyPattern(nonLocalizedPattern);
return dateFormat;
}
public Class getTypeClass() {
return Date.class;
}
/**
*
* @param style one of the constants FULL, LONG, MEDIUM or SHORT defined in the {@link Date} class.
*/
public void setStyle(int style) {
this.style = style;
}
public void setVariant(int variant) {
if (variant != DATE && variant != TIME && variant != DATE_TIME)
throw new IllegalArgumentException("Invalid value for variant parameter.");
this.variant = variant;
}
public void addFormattingPattern(Locale locale, String pattern) {
localizedPatterns.put(locale, pattern);
}
public void setNonLocalizedPattern(String pattern) {
this.nonLocalizedPattern = pattern;
}
}