001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.betwixt.strategy;
018:
019: import java.text.ParseException;
020: import java.text.SimpleDateFormat;
021: import java.util.Locale;
022:
023: import org.apache.commons.beanutils.ConversionException;
024: import org.apache.commons.betwixt.expression.Context;
025:
026: /**
027: * <p>Default string <-> object conversion strategy.</p>
028: * <p>
029: * This delegates to ConvertUtils except when the type
030: * is assignable from <code>java.util.Date</code>
031: * but not from <code>java.sql.Date</code>.
032: * In this case, the format used is (in SimpleDateFormat terms)
033: * <code>EEE MMM dd HH:mm:ss zzz yyyy</code>.
034: * This is the same as the output of the toString method on java.util.Date.
035: * </p>
036: * <p>
037: * This should preserve the existing symantic behaviour whilst allowing round tripping of dates
038: * (given the default settings).
039: * </p>
040: * @author Robert Burrell Donkin
041: * @since 0.5
042: */
043: public class DefaultObjectStringConverter extends
044: ConvertUtilsObjectStringConverter {
045:
046: /** Formats Dates to Strings and Strings to Dates */
047: private final SimpleDateFormat formatter = new SimpleDateFormat(
048: "EEE MMM dd HH:mm:ss zzz yyyy", Locale.UK);
049:
050: /**
051: * Converts an object to a string representation using ConvertUtils.
052: * If the object is a java.util.Date and the type is java.util.Date
053: * but not java.sql.Date
054: * then SimpleDateFormat formatting to
055: * <code>EEE MMM dd HH:mm:ss zzz yyyy</code>
056: * will be used.
057: * (This is the same as java.util.Date toString would return.)
058: *
059: * @param object the object to be converted, possibly null
060: * @param type the property class of the object, not null
061: * @param flavour a string allow symantic differences in formatting
062: * to be communicated (ignored)
063: * @param context convert against this context not null
064: * @return a String representation, not null
065: */
066: public String objectToString(Object object, Class type,
067: String flavour, Context context) {
068: if (object != null) {
069: if (object instanceof Class) {
070: return ((Class) object).getName();
071: }
072:
073: if (object instanceof java.util.Date && isUtilDate(type)) {
074:
075: return formatter.format((java.util.Date) object);
076:
077: } else {
078: // use ConvertUtils implementation
079: return super .objectToString(object, type, flavour,
080: context);
081: }
082: }
083: return "";
084: }
085:
086: /**
087: * Converts an object to a string representation using ConvertUtils.
088: *
089: * @param value the String to be converted, not null
090: * @param type the property class to be returned (if possible), not null
091: * @param flavour a string allow symantic differences
092: * in formatting to be communicated (ignored)
093: * @param context not null
094: * @return an Object converted from the String, not null
095: */
096: public Object stringToObject(String value, Class type,
097: String flavour, Context context) {
098: if (isUtilDate(type)) {
099: try {
100:
101: return formatter.parse(value);
102:
103: } catch (ParseException ex) {
104: handleException(ex);
105: // this supports any subclasses that do not which to throw exceptions
106: // probably will result in a problem when the method will be invoked
107: // but never mind
108: return value;
109: }
110: } else {
111: // use ConvertUtils implementation
112: return super .stringToObject(value, type, flavour, context);
113: }
114: }
115:
116: /**
117: * Allow subclasses to use a different exception handling strategy.
118: * This class throws a <code>org.apache.commons.beanutils.ConversionException</code>
119: * when conversion fails.
120: * @param e the Exception to be handled
121: * @throws org.apache.commons.beanutils.ConversionException when conversion fails
122: */
123: protected void handleException(Exception e) {
124: throw new ConversionException(
125: "String to object conversion failed: " + e.getMessage(),
126: e);
127: }
128:
129: /**
130: * Is the given type a java.util.Date but not a java.sql.Date?
131: * @param type test this class type
132: * @return true is this is a until date but not a sql one
133: */
134: private boolean isUtilDate(Class type) {
135: return (java.util.Date.class.isAssignableFrom(type)
136: && !java.sql.Date.class.isAssignableFrom(type)
137: && !java.sql.Time.class.isAssignableFrom(type) && !java.sql.Timestamp.class
138: .isAssignableFrom(type));
139: }
140: }
|