/**
 *
 */
package com.sybase.it.cosmos.dao.impl.ibatis.extentions;

import java.io.IOException;
import java.sql.SQLException;

import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;

/**
 * @author cmathrus
 *
 */
public abstract class StreamTypeHandlerCallback implements TypeHandlerCallback {

	/**
	 * Converts the passed in Object parameter into a java.io.InputStream ready for consumption.
	 * The assumption here is that the passed in Object should be
	 * of type java.lang.String or a byte[]. In addition, null is supported. If a null
	 * is passed in then an empty InputStream will still be returned.
	 *
	 * @param parameter
	 * @return The InputStream that is wrapping the passed in object.
	 * @throws SQLException If the passed in object is not one of the defined types listed above.
	 */
	protected java.io.InputStream convertToInputStream(Object parameter)
		throws SQLException {
		byte[] bytes = null;

		if(parameter == null) {
			bytes = null;
		}
		else if(parameter.getClass().isAssignableFrom(byte[].class)) {
			bytes = (byte[]) parameter;
		}
		else if(parameter.getClass().isAssignableFrom(String.class)) {
			bytes = ((String)parameter).getBytes();
		}
		else {
			throw new java.sql.SQLException("Unsupported datatype! Expected java.lang.String or byte[] but found: " + parameter.getClass());
		}

		return new java.io.ByteArrayInputStream(bytes);
	}

	/**
	 * Converts the passed in java.io.InputStream into a ByteArrayOutputStream that is ready for consumption.
	 * @param is
	 * @return
	 * @throws java.sql.SQLException If an IOException occurs it will be wrapped in an SQLException
	 */
	protected java.io.ByteArrayOutputStream  getAsOutputStream(java.io.InputStream is) throws java.sql.SQLException {

		if(is == null) {
			return null;
		}

		java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream();

		byte bytes[] = new byte[10000];
		try {
			for (int numRead = is.read(bytes); numRead != -1; numRead = is.read(bytes)) {
				os.write(bytes, 0, numRead);
			}
		} catch (IOException e) {
			throw new java.sql.SQLException(e.getMessage());
		} finally {
			try {
				is.close();
			} catch (java.io.IOException e) {
				// ignore
			}
		}

		return os;
	}

	/**
	 * Converts the passed in parameter object into a java.io.InputStream that can be consumed
	 * by the passed in setter. The InputStream is set using the setters setAsciiStream method.
	 * @param setter
	 * @param parameter
	 * @throws SQLException If an IOException occurs it is wrapped within an SQLException.
	 */
	public void setAsciiStream(ParameterSetter setter, Object parameter)
		throws SQLException {

		if(parameter == null) {
			setter.setNull(java.sql.Types.LONGVARCHAR);
		}
		else {
			java.io.InputStream is = convertToInputStream(parameter);
			try {
				setter.setAsciiStream(is, is.available());
			} catch (IOException e) {
				throw new java.sql.SQLException(e.getMessage());
			}
		}
	}

	/**
	 * Converts the passed in parameter object into a java.io.InputStream that can be consumed
	 * by the passed in setter. The InputStream is set using the setters setBinaryStream method.
	 * @param setter
	 * @param parameter
	 * @throws SQLException If an IOException occurs it is wrapped within an SQLException.
	 */
	public void setBinaryStream(ParameterSetter setter, Object parameter)
		throws SQLException {

		if(parameter == null) {
			setter.setNull(java.sql.Types.LONGVARBINARY);
		}
		else {
			java.io.InputStream is = convertToInputStream(parameter);
			try {
				setter.setBinaryStream(is, is.available());
			} catch (IOException e) {
				throw new java.sql.SQLException(e.getMessage());
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.ibatis.sqlmap.client.extensions.TypeHandlerCallback#valueOf(java.lang.String)
	 */
	public Object valueOf(String s) {
		return s;
	}
}
