package org.nnsoft.guice.rocoto.converters;
/*
* Copyright 2009-2012 The 99 Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
/**
* Converter implementation for {@code java.util.Calendar} and {@code java.util.Date}.
*/
public final class DateConverter
extends AbstractConverter<Date>
{
private final List<String> patterns = new ArrayList<String>();
private Locale locale;
private TimeZone timeZone;
public DateConverter()
{
// ISO date formats
this.addPattern( "yyyy" );
this.addPattern( "yyyy-MM" );
this.addPattern( "yyyy-MM-dd" );
this.addPattern( "yyyy-MM-dd'T'hh:mmZ" );
this.addPattern( "yyyy-MM-dd'T'hh:mm:ssZ" );
this.addPattern( "yyyy-MM-dd'T'hh:mm:ss.sZ" );
}
public void setLocale( Locale locale )
{
this.locale = locale;
}
public void setTimeZone( TimeZone timeZone )
{
this.timeZone = timeZone;
}
public void addPattern( String pattern )
{
this.patterns.add( pattern );
}
/**
* {@inheritDoc}
*/
public Object convert( String value, TypeLiteral<?> toType )
{
Exception firstEx = null;
for ( String pattern : this.patterns )
{
try
{
DateFormat format;
if ( this.locale != null )
{
format = new SimpleDateFormat( pattern, this.locale );
}
else
{
format = new SimpleDateFormat( pattern );
}
if ( this.timeZone != null )
{
format.setTimeZone( this.timeZone );
}
format.setLenient( false );
Date date = this.parse( value, format );
if ( Calendar.class == toType.getType() )
{
Calendar calendar = null;
if ( this.locale == null && this.timeZone == null )
{
calendar = Calendar.getInstance();
}
else if ( this.locale == null )
{
calendar = Calendar.getInstance( this.timeZone );
}
else if ( this.timeZone == null )
{
calendar = Calendar.getInstance( this.locale );
}
else
{
calendar = Calendar.getInstance( this.timeZone, this.locale );
}
calendar.setTime( date );
calendar.setLenient( false );
return calendar;
}
return date;
}
catch ( Exception ex )
{
if ( firstEx == null )
{
firstEx = ex;
}
}
}
throw new IllegalArgumentException( "Error converting '" + value + "' using patterns " + this.patterns,
firstEx );
}
private Date parse( String value, DateFormat format )
{
ParsePosition pos = new ParsePosition( 0 );
Date parsedDate = format.parse( value, pos ); // ignore the result (use the Calendar)
if ( pos.getErrorIndex() >= 0 || pos.getIndex() != value.length() || parsedDate == null )
{
String msg = "Error converting '" + value + "'";
if ( format instanceof SimpleDateFormat )
{
msg += " using pattern '" + ( (SimpleDateFormat) format ).toPattern() + "'";
}
throw new ProvisionException( msg );
}
return parsedDate;
}
}