/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/

/*
 * Created on Mar 14, 2005
 *
 */
package gov.va.med.esr.common.persistent.hibernate;

// Java classes
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.hibernate.HibernateException;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;

import gov.va.med.esr.common.infra.TriState;

/**
 * @author Yi He
 * @version 1.0
 */
public class TriStateType
    implements UserType
{
    private static final String KEY_TRUE = "Y";
    private static final String KEY_FALSE = "N";
    private static final String KEY_UNKNOWN = "U";

    private final StringType stringType;

    public TriStateType()
    {
        super();

        this.stringType = new StringType();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#sqlTypes()
     */
    public int[] sqlTypes()
    {
        return new int[] { this.stringType.sqlType() };
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#returnedClass()
     */
    public Class returnedClass()
    {
        return TriState.class;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
     */
    public boolean equals(Object x, Object y) throws HibernateException
    {
        return ((x == y) || ((x != null) && x.equals(y)));
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#nullSafeGet(java.sql.ResultSet,
     *      java.lang.String[], java.lang.Object)
     */
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
        throws HibernateException,
        SQLException
    {
        String string = (String)this.stringType.nullSafeGet(rs, names[0]);

        if(KEY_TRUE.equals(string))
        {
            return TriState.TRUE;
        }
        else if(KEY_FALSE.equals(string))
        {
            return TriState.FALSE;
        }
        else if(KEY_UNKNOWN.equals(string))
        {
            return TriState.UNKNOWN;
        }
        else
        {
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement,
     *      java.lang.Object, int)
     */
    public void nullSafeSet(PreparedStatement st, Object value, int index)
        throws HibernateException,
        SQLException
    {
        String string = null;
        if(TriState.TRUE.equals(value))
        {
            string = KEY_TRUE;
        }
        else if(TriState.FALSE.equals(value))
        {
            string = KEY_FALSE;
        }
        else if(TriState.UNKNOWN.equals(value))
        {
            string = KEY_UNKNOWN;
        }
        else
        {
            string = null;
        }

        this.stringType.nullSafeSet(st, string, index);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#deepCopy(java.lang.Object)
     */
    public Object deepCopy(Object value) throws HibernateException
    {
        //The type is immutable so it's ok to return the same instance.
        return value;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.hibernate.UserType#isMutable()
     */
    public boolean isMutable()
    {
        return false;
    }

	/* (non-Javadoc)
	 * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
	 */
	public int hashCode(Object x) throws HibernateException {
		return x != null ? x.hashCode() : 0;
	}

	/* (non-Javadoc)
	 * @see org.hibernate.usertype.UserType#disassemble(java.lang.Object)
	 */
	public Serializable disassemble(Object value) throws HibernateException {		
		return (Serializable)value;
	}

	/* (non-Javadoc)
	 * @see org.hibernate.usertype.UserType#assemble(java.io.Serializable, java.lang.Object)
	 */
	public Object assemble(Serializable cached, Object owner) throws HibernateException {		
		return cached;
	}

	/* (non-Javadoc)
	 * @see org.hibernate.usertype.UserType#replace(java.lang.Object, java.lang.Object, java.lang.Object)
	 */
	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		return original;
	}

}