1 package org.apache.fulcrum.intake.model;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.text.DateFormat;
23 import java.text.ParseException;
24 import java.util.Date;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.fulcrum.intake.IntakeException;
28 import org.apache.fulcrum.intake.IntakeRuntimeException;
29 import org.apache.fulcrum.intake.validator.DateStringValidator;
30 import org.apache.fulcrum.intake.validator.Validator;
31
32
33 /**
34 * Field for date inputs as free form text. The parsing of date strings
35 * is dependent on any rules that are defined, so this field will expect that
36 * any validator will be (or extend) DateStringValidator.
37 *
38 * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
39 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
40 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
41 * @version $Id$
42 */
43 public class DateStringField
44 extends Field<Date>
45 {
46 /** Serial version */
47 private static final long serialVersionUID = 3659498567870484883L;
48
49 /** date format */
50 private DateFormat df = null;
51
52 /**
53 * Constructor.
54 *
55 * @param field xml field definition object
56 * @param group xml group definition object
57 * @throws IntakeException thrown by superclass
58 */
59 public DateStringField(XmlField field, Group group)
60 throws IntakeException
61 {
62 super(field, group);
63
64 Validator<?> validator = getValidator();
65 if (validator == null || !(validator instanceof DateStringValidator))
66 {
67 df = DateFormat.getInstance();
68 df.setLenient(true);
69 }
70 }
71
72 /**
73 * Sets the default value for a DateString field
74 *
75 * @param prop Parameter for the default values
76 */
77 @Override
78 public void setDefaultValue(String prop)
79 {
80 defaultValue = null;
81
82 if (prop == null)
83 {
84 return;
85 }
86
87 try
88 {
89 defaultValue = getDate(prop);
90 }
91 catch (ParseException e)
92 {
93 throw new IntakeRuntimeException("Could not parse " + prop
94 + " into a valid Date for the default value", e);
95 }
96 }
97
98 /**
99 * Set the empty Value. This value is used if Intake
100 * maps a field to a parameter returned by the user and
101 * the corresponding field is either empty (empty string)
102 * or non-existant.
103 *
104 * @param prop The value to use if the field is empty.
105 */
106 @Override
107 public void setEmptyValue(String prop)
108 {
109 emptyValue = null;
110
111 if (prop == null)
112 {
113 return;
114 }
115
116 try
117 {
118 emptyValue = getDate(prop);
119 }
120 catch (ParseException e)
121 {
122 throw new IntakeRuntimeException("Could not parse " + prop
123 + " into a valid Date for the empty value", e);
124 }
125 }
126
127 /**
128 * A suitable validator.
129 *
130 * @return "DateStringValidator"
131 */
132 @Override
133 protected String getDefaultValidator()
134 {
135 return DateStringValidator.class.getName();
136 }
137
138 /**
139 * Sets the value of the field from data in the parser.
140 */
141 @Override
142 protected void doSetValue()
143 {
144 if (isMultiValued())
145 {
146 String[] inputs = parser.getStrings(getKey());
147 Date[] values = new Date[inputs.length];
148 for (int i = 0; i < inputs.length; i++)
149 {
150 try
151 {
152 values[i] = StringUtils.isNotEmpty(inputs[i])
153 ? getDate(inputs[i]) : getEmptyValue();
154 }
155 catch (ParseException e)
156 {
157 values[i] = null;
158 }
159 }
160 setTestValue(values);
161 }
162 else
163 {
164 String val = parser.getString(getKey());
165 try
166 {
167 setTestValue(StringUtils.isNotEmpty(val) ? getDate(val) : getEmptyValue());
168 }
169 catch (ParseException e)
170 {
171 setTestValue(null);
172 }
173 }
174 }
175
176 /**
177 * Parses a test date string using the Validator if it exists and
178 * is an instance of DateStringValidator. Otherwise, DateFormat.parse()
179 * is used.
180 *
181 * @param dateString The string date to parse
182 * @return A <code>Date</code> object
183 * @throws ParseException The date could not be parsed.
184 */
185 private Date getDate(String dateString)
186 throws ParseException
187 {
188 Date date = null;
189 // FIXME: Canonicalize user-entered date strings.
190 Validator<?> validator = getValidator();
191 if (validator != null && validator instanceof DateStringValidator)
192 {
193 date = ((DateStringValidator) validator).parse(dateString);
194 }
195 else
196 {
197 date = df.parse(dateString);
198 }
199 return date;
200 }
201
202 /**
203 * returns a String representation
204 *
205 * @return a String representation
206 */
207 @Override
208 public String toString()
209 {
210 String s = null;
211 Object value = getValue();
212 Validator<?> validator = getValidator();
213 if (value == null)
214 {
215 s = "";
216 }
217 else if (value instanceof String)
218 {
219 s = (String) value;
220 }
221 else if (validator != null && validator instanceof DateStringValidator)
222 {
223 s = ((DateStringValidator) validator).format((Date) value);
224 }
225 else
226 {
227 s = df.format((Date) value);
228 }
229 return s;
230 }
231 }