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 ConvertUtilsObjectStringConverter {
044
045 /** Formats Dates to Strings and Strings to Dates */
046 private final SimpleDateFormat formatter
047 = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.UK);
048
049 /**
050 * Converts an object to a string representation using ConvertUtils.
051 * If the object is a java.util.Date and the type is java.util.Date
052 * but not java.sql.Date
053 * then SimpleDateFormat formatting to
054 * <code>EEE MMM dd HH:mm:ss zzz yyyy</code>
055 * will be used.
056 * (This is the same as java.util.Date toString would return.)
057 *
058 * @param object the object to be converted, possibly null
059 * @param type the property class of the object, not null
060 * @param flavour a string allow symantic differences in formatting
061 * to be communicated (ignored)
062 * @param context convert against this context not null
063 * @return a String representation, not null
064 */
065 public String objectToString(Object object, Class type, String flavour, Context context) {
066 if ( object != null ) {
067 if ( object instanceof Class) {
068 return ((Class) object).getName();
069 }
070
071 if ( object instanceof java.util.Date && isUtilDate( type ) ) {
072
073 return formatter.format( (java.util.Date) object );
074
075 } else {
076 // use ConvertUtils implementation
077 return super.objectToString( object, type, flavour, context );
078 }
079 }
080 return "";
081 }
082
083 /**
084 * Converts an object to a string representation using ConvertUtils.
085 *
086 * @param value the String to be converted, not null
087 * @param type the property class to be returned (if possible), not null
088 * @param flavour a string allow symantic differences
089 * in formatting to be communicated (ignored)
090 * @param context not null
091 * @return an Object converted from the String, not null
092 */
093 public Object stringToObject(String value, Class type, String flavour, Context context) {
094 if ( isUtilDate( type ) ) {
095 try {
096
097 return formatter.parse( value );
098
099 } catch ( ParseException ex ) {
100 handleException( ex );
101 // this supports any subclasses that do not which to throw exceptions
102 // probably will result in a problem when the method will be invoked
103 // but never mind
104 return value;
105 }
106 } else {
107 // use ConvertUtils implementation
108 return super.stringToObject( value, type, flavour, context );
109 }
110 }
111
112 /**
113 * Allow subclasses to use a different exception handling strategy.
114 * This class throws a <code>org.apache.commons.beanutils.ConversionException</code>
115 * when conversion fails.
116 * @param e the Exception to be handled
117 * @throws org.apache.commons.beanutils.ConversionException when conversion fails
118 */
119 protected void handleException(Exception e) {
120 throw new ConversionException( "String to object conversion failed: " + e.getMessage(), e );
121 }
122
123 /**
124 * Is the given type a java.util.Date but not a java.sql.Date?
125 * @param type test this class type
126 * @return true is this is a until date but not a sql one
127 */
128 private boolean isUtilDate(Class type) {
129 return ( java.util.Date.class.isAssignableFrom(type)
130 && !java.sql.Date.class.isAssignableFrom(type)
131 && !java.sql.Time.class.isAssignableFrom(type)
132 && !java.sql.Timestamp.class.isAssignableFrom(type) );
133 }
134 }