Source code: org/scopemvc/util/convertor/DateStringConvertor.java
1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, Steve Meyfroidt
4 * All rights reserved.
5 * Email: smeyfroi@users.sourceforge.net
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * Neither the name "Scope" nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 *
37 * $Id: DateStringConvertor.java,v 1.5 2002/01/26 09:46:20 smeyfroi Exp $
38 */
39
40
41 package org.scopemvc.util.convertor;
42
43
44 import java.text.DateFormat;
45 import java.text.ParseException;
46 import java.text.SimpleDateFormat;
47 import java.util.ArrayList;
48 import java.util.Date;
49 import java.util.Iterator;
50 import java.util.List;
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogSource;
53 import org.scopemvc.util.ScopeConfig;
54
55
56 /**
57 * String convertor for type <code>java.util.Date</code>. The Time part
58 * of <code>Date</code> instances are ignored. See
59 * {@link DateTimeStringConvertor DateTimeStringConvertor} and
60 * {@link TimeStringConvertor TimeStringConvertor}.
61 * <p>
62 * It uses one java.text.DateFormat for converting
63 * into <code>String</code> and set of <code>DateFormat</code>s for
64 * parsing. Parsing formats are successively used to try to parse until
65 * one is successful.
66 * </p>
67 * <p>
68 * Formats are picked up from config (see
69 * {@link org.scopemvc.util.DefaultScopeConfig} for details)
70 * or if none in config, the default formatter is:
71 * <pre>
72 * DateFormat.getDateInstance(DateFormat.MEDIUM)
73 * </pre>
74 * and default parsers are:
75 * <pre>
76 * DateFormat.getDateInstance(DateFormat.FULL);
77 * DateFormat.getDateInstance(DateFormat.LONG);
78 * DateFormat.getDateInstance(DateFormat.MEDIUM);
79 * DateFormat.getDateInstance(DateFormat.SHORT);
80 * </pre>
81 * <i>Note:</i> the default parsing set is initialized during class loading
82 * and based on default platform locale. If application uses other locales,
83 * there will be need to set parsing objects explicitly.
84 *
85 * @author <A HREF="mailto:danmi@users.sourceforge.net">Daniel Michalik</A>
86 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
87 * @version $Revision: 1.5 $ $Date: 2002/01/26 09:46:20 $
88 * @see DateTimeStringConvertor
89 * @see TimeStringConvertor
90 */
91 public class DateStringConvertor extends NullStringConvertor {
92
93
94 private static final Log LOG = LogSource.getInstance(DateStringConvertor.class);
95
96
97 private DateFormat formatter;
98 private DateFormat parsers[];
99
100
101 // ------------- Defaults if no config specified ----------------
102 private static final DateFormat defaultParsers[] = new DateFormat[4];
103 static {
104 defaultParsers[3] = DateFormat.getDateInstance(DateFormat.SHORT);
105 defaultParsers[3].setLenient(false);
106 defaultParsers[2] = DateFormat.getDateInstance(DateFormat.MEDIUM);
107 defaultParsers[2].setLenient(false);
108 defaultParsers[1] = DateFormat.getDateInstance(DateFormat.LONG);
109 defaultParsers[1].setLenient(false);
110 defaultParsers[0] = DateFormat.getDateInstance(DateFormat.FULL);
111 defaultParsers[0].setLenient(false);
112 }
113 // ------------------------------------------------------------------
114
115
116 /**
117 * Creates new DateStringConvertor. If formats and parsers
118 * are specified in config then use those else use current locale default
119 * format and platform locale default parsers.
120 */
121 public DateStringConvertor() {
122 initDefaults();
123 }
124
125
126 protected void initDefaults() {
127 Object configFormatter = ScopeConfig.getObject(getClass().getName() + ".formatter");
128 setFormatter(configFormatter);
129
130 List parserList = new ArrayList();
131 for (Iterator i = ScopeConfig.getKeysMatching(getClass().getName() + ".parser"); i.hasNext(); ) {
132 parserList.add(ScopeConfig.getObject((String)i.next()));
133 }
134 if (parserList.size() < 1) {
135 setParsers(getDefaultParsers());
136 } else {
137 setParsers(parserList.toArray());
138 }
139 }
140
141
142 // /** for debug only */
143 // public final void dumpConfig() {
144 // LOG.info(getClass().getName());
145 // LOG.info(formatter.format(new Date(0)));
146 // LOG.info("Number of parsers: " + parsers.length);
147 // for (int i = 0; i < parsers.length; i++) {
148 // LOG.info(Integer.toString(i) + ": " + parsers[i].format(new Date(0)));
149 // }
150 // }
151
152
153 protected DateFormat[] getDefaultParsers() {
154 return DateStringConvertor.defaultParsers;
155 }
156
157
158 /**
159 * Creates new DateStringConvertor with specified formatter and parsers.
160 */
161 public DateStringConvertor(DateFormat inFormatter, DateFormat inParsers[]) {
162 setFormatter(inFormatter);
163 setParsers(inParsers);
164 }
165
166
167 /**
168 * Sets format used by this convertor for converting
169 * <code>Date</code>s into <code>String</code>s.
170 *
171 * @param Object either a DateFormat or a String pattern
172 * used to create a SimpleDateFormat from.
173 * @throws IllegalArgumentException if passed format is null or
174 * not a DateFormat or not a String.
175 */
176 public final void setFormatter(Object inFormat) {
177 if (inFormat instanceof DateFormat) {
178 formatter = (DateFormat)inFormat;
179 } else if (inFormat instanceof String) {
180 formatter = new SimpleDateFormat((String)inFormat);
181 } else {
182 throw new IllegalArgumentException("Can't set formatter to: " + inFormat);
183 }
184 }
185
186
187 /**
188 * Set parser array for this converter.
189 * @param Object[] array of either DateFormats or Strings
190 * used to create SimpleDateFormat objects.
191 * @throws IllegalArgumentException if the array is <code>null</code>
192 * or contains a non-String or non-DateFormat object.
193 */
194 public final void setParsers(Object[] inParsers) {
195 if (inParsers == null) {
196 throw new IllegalArgumentException("Passed array of formats cannot be null");
197 }
198
199 parsers = new DateFormat[inParsers.length];
200 for (int i = 0; i < inParsers.length; i++) {
201 if (LOG.isDebugEnabled()) LOG.debug("setParsers: " + inParsers[i]);
202 if (inParsers[i] instanceof String) {
203 SimpleDateFormat f = new SimpleDateFormat((String)inParsers[i]);
204 f.setLenient(false);
205 parsers[i] = f;
206 } else if (inParsers[i] instanceof DateFormat) {
207 parsers[i] = (DateFormat)inParsers[i];
208 } else {
209 throw new IllegalArgumentException("Cannot set a parser to be: " + inParsers[i]);
210 }
211 }
212 }
213
214
215 /**
216 * Returns instance of <code>java.util.Date</code>.Parsing formats
217 * are successively used to try to parse until one is successful
218 * or exception is thrown.
219 * <p>Empty, <code>null</code> and {@link #getNullAsString()
220 * getNullAsString()} strings are converted into <code>null</code>.
221 * </p>
222 *
223 * @throws IllegalArgumentException
224 * if can't convert from String using current
225 * {@link java.text.DateFormat DateFormat}
226 */
227 public Object stringAsValue(String inString) throws IllegalArgumentException {
228
229 if (isNull(inString)) {
230 return null;
231 }
232
233 for (int i = parsers.length - 1; i >= 0; i--) {
234 if (LOG.isDebugEnabled()) LOG.debug("Parser: " + inString + ", " + parsers[i].format(new Date(0)));
235 try {
236 Date result = parsers[i].parse(inString);
237 if (result != null) {
238 return result;
239 }
240 } catch (ParseException ex) {
241 if (LOG.isDebugEnabled()) LOG.debug("stringAsValue", ex);
242 // ignore and try again
243 }
244 }
245 throw new IllegalArgumentException("Cannot convert to Date/Time: " + inString);
246 }
247
248
249 /**
250 * @return text representation of Date object. For null argument
251 * is called method {@link #getNullAsString() getNullAsString}
252 * @throws IllegalArgumentException
253 * it argument is not instance of
254 * {@link java.util.Date java.util.Date}
255 */
256 public String valueAsString(Object inValue) throws IllegalArgumentException {
257 if (inValue == null) {
258 return getNullAsString();
259 }
260 if (! (inValue instanceof Date)) {
261 throw new IllegalArgumentException("Passed object is not subclass "
262 + "of java.util.Date. Its class is "+inValue.getClass());
263 }
264 return formatter.format(inValue);
265 }
266 }