001: /*
002: * Copyright 2002-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.springframework.beans.propertyeditors;
018:
019: import java.beans.PropertyEditorSupport;
020: import java.text.DateFormat;
021: import java.text.ParseException;
022: import java.util.Date;
023:
024: import org.springframework.util.StringUtils;
025:
026: /**
027: * PropertyEditor for <code>java.util.Date</code>, supporting a custom
028: * <code>java.text.DateFormat</code>.
029: *
030: * <p>This is not meant to be used as system PropertyEditor but rather as
031: * locale-specific date editor within custom controller code, to parse
032: * user-entered date strings into Date properties of beans, and render
033: * them in the UI form.
034: *
035: * <p>In web MVC code, this editor will typically be registered with
036: * <code>binder.registerCustomEditor</code> calls in an implementation
037: * of BaseCommandController's <code>initBinder</code> method.
038: *
039: * @author Juergen Hoeller
040: * @since 28.04.2003
041: * @see java.util.Date
042: * @see java.text.DateFormat
043: * @see org.springframework.validation.DataBinder#registerCustomEditor
044: * @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder
045: */
046: public class CustomDateEditor extends PropertyEditorSupport {
047:
048: private final DateFormat dateFormat;
049:
050: private final boolean allowEmpty;
051:
052: private final int exactDateLength;
053:
054: /**
055: * Create a new CustomDateEditor instance, using the given DateFormat
056: * for parsing and rendering.
057: * <p>The "allowEmpty" parameter states if an empty String should
058: * be allowed for parsing, i.e. get interpreted as null value.
059: * Otherwise, an IllegalArgumentException gets thrown in that case.
060: * @param dateFormat DateFormat to use for parsing and rendering
061: * @param allowEmpty if empty strings should be allowed
062: */
063: public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty) {
064: this .dateFormat = dateFormat;
065: this .allowEmpty = allowEmpty;
066: this .exactDateLength = -1;
067: }
068:
069: /**
070: * Create a new CustomDateEditor instance, using the given DateFormat
071: * for parsing and rendering.
072: * <p>The "allowEmpty" parameter states if an empty String should
073: * be allowed for parsing, i.e. get interpreted as null value.
074: * Otherwise, an IllegalArgumentException gets thrown in that case.
075: * <p>The "exactDateLength" parameter states that IllegalArgumentException gets
076: * thrown if the String does not exactly match the length specified. This is useful
077: * because SimpleDateFormat does not enforce strict parsing of the year part,
078: * not even with <code>setLenient(false)</code>. Without an "exactDateLength"
079: * specified, the "01/01/05" would get parsed to "01/01/0005".
080: * @param dateFormat DateFormat to use for parsing and rendering
081: * @param allowEmpty if empty strings should be allowed
082: * @param exactDateLength the exact expected length of the date String
083: */
084: public CustomDateEditor(DateFormat dateFormat, boolean allowEmpty,
085: int exactDateLength) {
086: this .dateFormat = dateFormat;
087: this .allowEmpty = allowEmpty;
088: this .exactDateLength = exactDateLength;
089: }
090:
091: /**
092: * Parse the Date from the given text, using the specified DateFormat.
093: */
094: public void setAsText(String text) throws IllegalArgumentException {
095: if (this .allowEmpty && !StringUtils.hasText(text)) {
096: // Treat empty String as null value.
097: setValue(null);
098: } else if (text != null && this .exactDateLength >= 0
099: && text.length() != this .exactDateLength) {
100: throw new IllegalArgumentException(
101: "Could not parse date: it is not exactly"
102: + this .exactDateLength + "characters long");
103: } else {
104: try {
105: setValue(this .dateFormat.parse(text));
106: } catch (ParseException ex) {
107: throw new IllegalArgumentException(
108: "Could not parse date: " + ex.getMessage());
109: }
110: }
111: }
112:
113: /**
114: * Format the Date as String, using the specified DateFormat.
115: */
116: public String getAsText() {
117: Date value = (Date) getValue();
118: return (value != null ? this .dateFormat.format(value) : "");
119: }
120:
121: }
|