001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.converter.basic;
018:
019: import java.text.DateFormat;
020: import java.text.Format;
021: import java.text.ParseException;
022: import java.text.SimpleDateFormat;
023: import java.util.Locale;
024: import java.util.TimeZone;
025:
026: import org.compass.core.converter.ConversionException;
027: import org.compass.core.mapping.ResourcePropertyMapping;
028: import org.compass.core.marshall.MarshallingContext;
029:
030: /**
031: * Converts dates to String and vice versa. Supports the notion of "now" using
032: * {@link org.compass.core.converter.basic.DateMathParser}.
033: *
034: * @author kimchy
035: */
036: public class DateConverter extends AbstractFormatConverter {
037:
038: public static final String DEFAULT_NOW_PREFIX = "now";
039:
040: public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd-HH-mm-ss-S-a";
041:
042: private static class DateFormatter implements
043: ThreadSafeFormat.FormatterFactory {
044:
045: private String format;
046:
047: private Locale locale;
048:
049: public void configure(String format, Locale locale) {
050: this .format = format;
051: this .locale = locale;
052: }
053:
054: public Format create() {
055: DateFormat dateFormat;
056: if (locale != null) {
057: dateFormat = new SimpleDateFormat(format, locale);
058: } else {
059: dateFormat = new SimpleDateFormat(format);
060: }
061: dateFormat.setLenient(false);
062: return dateFormat;
063: }
064: }
065:
066: protected String doGetDefaultFormat() {
067: return DEFAULT_DATE_FORMAT;
068: }
069:
070: protected ThreadSafeFormat.FormatterFactory doCreateFormatterFactory() {
071: return new DateConverter.DateFormatter();
072: }
073:
074: /**
075: * Try all the configured formatters to format the str into an Object.
076: */
077: protected Object doFromString(String str,
078: ResourcePropertyMapping resourcePropertyMapping,
079: MarshallingContext context) throws ConversionException {
080: try {
081: if (str.toLowerCase().startsWith(DEFAULT_NOW_PREFIX)) {
082: // TODO have timezone pluggable
083: DateMathParser p = new DateMathParser(TimeZone
084: .getDefault(), locale);
085: return p.parseMath(str.substring(DEFAULT_NOW_PREFIX
086: .length()));
087: }
088: for (int i = 0; i < formatters.length; i++) {
089: try {
090: return formatters[i].parse(str);
091: } catch (ParseException e) {
092: // do nothing, continue to the next one
093: }
094: }
095: throw new ConversionException("Failed to parse date ["
096: + str + "]");
097: } catch (ParseException e) {
098: throw new ConversionException("Failed to parse date ["
099: + str + "]", e);
100: }
101: }
102:
103: /**
104: * Uses the first configured formatter (also known as the default one) to convert it to String.
105: */
106: protected String doToString(Object o,
107: ResourcePropertyMapping resourcePropertyMapping,
108: MarshallingContext context) {
109: return formatters[0].format(o);
110: }
111: }
|