001    package com.mockrunner.jdbc;
002    
003    import java.io.InputStream;
004    import java.io.Reader;
005    
006    import com.mockrunner.mock.jdbc.MockResultSet;
007    import com.mockrunner.util.common.ArrayUtil;
008    import com.mockrunner.util.common.MethodUtil;
009    import com.mockrunner.util.common.StreamUtil;
010    
011    /**
012     * Util class for <code>PreparedStatement</code> and <code>ResultSet</code>
013     * parameters.
014     */
015    public class ParameterUtil
016    {
017        /**
018         * Copies a parameter of a <code>PreparedStatement</code>,
019         * <code>CallableStatement</code> or a <code>ResultSet</code> value.
020         * <code>InputStream</code> objects, <code>Reader</code> objects 
021         * and arrays are copied into new allocated streams or arrays.
022         * All other objects are cloned by calling the clone method. 
023         * If the object is not cloneable, it is returned unchanged.
024         * @param source the parameter to copy
025         * @return a copy of the parameter
026         */
027        public static Object copyParameter(Object source)
028        {
029            if(null == source) return null;
030            if(source.getClass().isArray())
031            {
032                return ArrayUtil.copyArray(source);
033            }
034            if(source instanceof InputStream)
035            {
036                return StreamUtil.copyStream((InputStream)source);
037            }
038            if(source instanceof Reader)
039            {
040                return StreamUtil.copyReader((Reader)source);
041            }
042            if(source instanceof Cloneable)
043            {
044                try
045                {
046                    return MethodUtil.invoke(source, "clone");
047                }
048                catch(Exception exc)
049                {
050                    return source;
051                }
052            }
053            return source;
054        }
055        
056        /**
057         * Compares two parameters of a <code>PreparedStatement</code> or
058         * <code>CallableStatement</code>. Can also be used to compare
059         * values of a <code>ResultSet</code>. It is used by
060         * {@link com.mockrunner.jdbc.PreparedStatementResultSetHandler}
061         * for comparing parameters specified in the <code>prepare</code>
062         * methods.
063         * Since the parameters can be of the type <code>byte[]</code>,
064         * <code>InputStream</code> and <code>Reader</code> this method handles 
065         * these types of objects. All other objects are compared using the 
066         * <code>equals</code> method. The mock versions of <code>Ref</code>,
067         * <code>Array</code>, <code>Blob</code>, <code>Clob</code>,
068         * <code>Struct</code> etc. all provide a suitable <code>equals</code>
069         * implementation.
070         * @param source the first parameter
071         * @param target the second parameter
072         * @return <code>true</code> if <i>source</i> is equal to <i>target</i>,
073         *         <code>false</code> otherwise
074         */
075        public static boolean compareParameter(Object source, Object target)
076        {
077            if(null == source && null == target) return true;
078            if(null == source || null == target) return false;
079            if(source instanceof InputStream && target instanceof InputStream)
080            {
081                return StreamUtil.compareStreams((InputStream)source, (InputStream)target);
082            }
083            if(source instanceof Reader && target instanceof Reader)
084            {
085                return StreamUtil.compareReaders((Reader)source, (Reader)target);
086            }
087            if(source instanceof MockResultSet && target instanceof MockResultSet)
088            {
089                return ((MockResultSet)source).isEqual((MockResultSet)target);
090            }
091            if(source.getClass().isArray() && target.getClass().isArray())
092            {
093                return ArrayUtil.areArraysEqual(source, target);
094            }
095            return source.equals(target);
096        }
097    }
098