
/********************************************************************
 * Copyright © 2008 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.persistent.hibernate;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.Date;

import org.hibernate.HibernateException;
import org.hibernate.type.ImmutableType;

import gov.va.med.fw.util.DateUtils;

/**
 * Even with a JPA interface, this is still needed to pass the desired UTC
 * TimeZone into the overloaded PreparedStatement setTimestamp(...) method.
 * 
 * <p>
 * Performs the standard conversion of the date based on a UTC calendar.
 * 
 * <p>
 * Hibernate annotation for target fields: <br>
 * 
 * <pre>
 * &amp;org.hibernate.annotations.Type(type = &quot;gov.va.med.fw.persistent.hibernate.UTCDateType&quot;)
 * </pre>
 * 
 * Oct 13, 2008
 * 
 * @author DNS   BOHMEG
 */
public class UTCDateType extends ImmutableType {
	/**
	 * 
	 */
	private static final long serialVersionUID = -7172333642500971775L;

	/*
	 * TODO: Do JDBC drivers ever change this Calendar instance? Is it
	 * thread-safe in the below usage for formatting?
	 */
	private static Calendar calendarUTC = Calendar.getInstance();

	static {
		// set the timezone for the calendar to UTC (= GMT)
		calendarUTC.setTimeZone(DateUtils.UTC_TIME_ZONE);
	}

	private static final int UTC_DATE_TYPE = Types.TIMESTAMP;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.NullableType#fromStringValue(java.lang.String)
	 */
	@Override
	public Object fromStringValue(String s) throws HibernateException {
		// TODO Auto-generated method stub
		return s;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.NullableType#get(java.sql.ResultSet,
	 * java.lang.String)
	 */
	@Override
	public Object get(ResultSet resultset, String s) throws HibernateException, SQLException {
		Timestamp sqlTimestamp = (Timestamp) resultset.getTimestamp(s, calendarUTC);
		return sqlTimestamp != null ? new Date(sqlTimestamp.getTime()) : null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.NullableType#set(java.sql.PreparedStatement,
	 * java.lang.Object, int)
	 */
	@Override
	public void set(PreparedStatement preparedstatement, Object obj, int i)
			throws HibernateException, SQLException {
		preparedstatement.setTimestamp(i, new Timestamp(((Date) obj).getTime()), calendarUTC);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.NullableType#sqlType()
	 */
	@Override
	public int sqlType() {
		// TODO Auto-generated method stub
		return UTC_DATE_TYPE;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.NullableType#toString(java.lang.Object)
	 */
	@Override
	public String toString(Object obj) throws HibernateException {
		// TODO Auto-generated method stub
		return obj != null ? obj.toString() : null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.Type#getName()
	 */
	public String getName() {
		// TODO Auto-generated method stub
		return getClass().getName();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.hibernate.type.Type#getReturnedClass()
	 */
	public Class getReturnedClass() {
		// TODO Auto-generated method stub
		return Date.class;
	}
}
