View Javadoc
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 }