/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.sql.rowset.serial;

import java.sql.*;
import java.io.*;
import java.util.Map;
import java.net.URL;


/**
 * A serialized version of an <code>Array</code>
 * object, which is the mapping in the Java programming language of an SQL
 * <code>ARRAY</code> value.
 * <P>
 * The <code>SerialArray</code> class provides a constructor for creating
 * a <code>SerialArray</code> instance from an <code>Array</code> object,
 * methods for getting the base type and the SQL name for the base type, and
 * methods for copying all or part of a <code>SerialArray</code> object.
 * <P>
 * Note: In order for this class to function correctly, a connection to the
 * data source
 * must be available in order for the SQL <code>Array</code> object to be
 * materialized (have all of its elements brought to the client server)
 * if necessary. At this time, logical pointers to the data in the data source,
 * such as locators, are not currently supported.
 */
public class SerialArray implements Array, Serializable, Cloneable {

        /**
         * A serialized array in which each element is an <code>Object</code>
         * in the Java programming language that represents an element
         * in the SQL <code>ARRAY</code> value.
         * @serial
         */
    private Object[] elements;

        /**
         * The SQL type of the elements in this <code>SerialArray</code> object.  The
         * type is expressed as one of the constants from the class
         * <code>java.sql.Types</code>.
         * @serial
         */
    private int baseType;

        /**
         * The type name used by the DBMS for the elements in the SQL <code>ARRAY</code>
         * value that this <code>SerialArray</code> object represents.
         * @serial
         */
    private String baseTypeName;

        /**
         * The number of elements in this <code>SerialArray</code> object, which
         * is also the number of elements in the SQL <code>ARRAY</code> value
         * that this <code>SerialArray</code> object represents.
         * @serial
         */
    private int len;

    /**
     * Constructs a new <code>SerialArray</code> object from the given
     * <code>Array</code> object, using the given type map for the custom
     * mapping of each element when the elements are SQL UDTs.
     * <P>
     * This method does custom mapping if the array elements are a UDT
     * and the given type map has an entry for that UDT.
     * Custom mapping is recursive,
     * meaning that if, for instance, an element of an SQL structured type
     * is an SQL structured type that itself has an element that is an SQL
     * structured type, each structured type that has a custom mapping will be
     * mapped according to the given type map.
     * <P>
     * The new <code>SerialArray</code>
     * object contains the same elements as the <code>Array</code> object
     * from which it is built, except when the base type is the SQL type
     * <code>STRUCT</code>, <code>ARRAY</code>, <code>BLOB</code>,
     * <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
     * In this case, each element in the new
     * <code>SerialArray</code> object is the appropriate serialized form,
     * that is, a <code>SerialStruct</code>, <code>SerialArray</code>,
     * <code>SerialBlob</code>, <code>SerialClob</code>,
     * <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
     * <P>
     * Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
     * object is created must have materialized the SQL <code>ARRAY</code> value's
     * data on the client before it is passed to the constructor.  Otherwise,
     * the new <code>SerialArray</code> object will contain no data.
     * <p>
     * Note: (2) If the <code>Array</code> contains <code>java.sql.Types.JAVA_OBJECT</code>
     * types, the <code>SerialJavaObject</code> constructor is called where checks
     * are made to ensure this object is serializable.
     * <p>
     * Note: (3) The <code>Array</code> object supplied to this constructor cannot
     * return <code>null</code> for any <code>Array.getArray()</code> methods.
     * <code>SerialArray</code> cannot serialize null array values.
     *
     *
     * @param array the <code>Array</code> object to be serialized
     * @param map a <code>java.util.Map</code> object in which
     *        each entry consists of 1) a <code>String</code> object
     *        giving the fully qualified name of a UDT (an SQL structured type or
     *        distinct type) and 2) the
     *        <code>Class</code> object for the <code>SQLData</code> implementation
     *        that defines how the UDT is to be mapped. The <i>map</i>
     *        parameter does not have any effect for <code>Blob</code>,
     *        <code>Clob</code>, <code>DATALINK</code>, or
     *        <code>JAVA_OBJECT</code> types.
     * @throws SerialException if an error occurs serializing the
     *        <code>Array</code> object
     * @throws SQLException if a database access error occurs or if the
     *        <i>array</i> or the <i>map</i> values are <code>null</code>
     */
     public SerialArray(Array array, Map<String,Class<?>> map)
         throws SerialException, SQLException
     {

        if ((array == null) || (map == null)) {
            throw new SQLException("Cannot instantiate a SerialArray " +
            "object with null parameters");
        }

        if ((elements = (Object[])array.getArray()) == null) {
             throw new SQLException("Invalid Array object. Calls to Array.getArray() " +
                 "return null value which cannot be serialized");
         }

        elements = (Object[])array.getArray(map);
        baseType = array.getBaseType();
        baseTypeName = array.getBaseTypeName();
        len = elements.length;

        switch (baseType) {
            case java.sql.Types.STRUCT:
                for (int i = 0; i < len; i++) {
                    elements[i] = new SerialStruct((Struct)elements[i], map);
                }
            break;

            case java.sql.Types.ARRAY:
                for (int i = 0; i < len; i++) {
                    elements[i] = new SerialArray((Array)elements[i], map);
                }
            break;

            case java.sql.Types.BLOB:
            for (int i = 0; i < len; i++) {
                elements[i] = new SerialBlob((Blob)elements[i]);
            }
            break;

            case java.sql.Types.CLOB:
                for (int i = 0; i < len; i++) {
                    elements[i] = new SerialClob((Clob)elements[i]);
                }
            break;

            case java.sql.Types.DATALINK:
                for (int i = 0; i < len; i++) {
                    elements[i] = new SerialDatalink((URL)elements[i]);
                }
            break;

            case java.sql.Types.JAVA_OBJECT:
                for (int i = 0; i < len; i++) {
                elements[i] = new SerialJavaObject((Object)elements[i]);
            }
        default:
            ;
        }
  }

    /**
     * This method frees the <code>Array</code> object and releases the resources that
     * it holds. The object is invalid once the <code>free</code>
     * method is called.
     *<p>
     * After <code>free</code> has been called, any attempt to invoke a
     * method other than <code>free</code> will result in a <code>SQLException</code>
     * being thrown.  If <code>free</code> is called multiple times, the subsequent
     * calls to <code>free</code> are treated as a no-op.
     *<p>
     *
     * @throws SQLException if an error occurs releasing
     * the Array's resources
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     * @since 1.6
     */
    public void free() throws SQLException {
         throw new SQLFeatureNotSupportedException("Feature not supported");
    }

    /**
     * Constructs a new <code>SerialArray</code> object from the given
     * <code>Array</code> object.
     * <P>
     * This constructor does not do custom mapping.  If the base type of the array
     * is an SQL structured type and custom mapping is desired, the constructor
     * <code>SerialArray(Array array, Map map)</code> should be used.
     * <P>
     * The new <code>SerialArray</code>
     * object contains the same elements as the <code>Array</code> object
     * from which it is built, except when the base type is the SQL type
     * <code>BLOB</code>,
     * <code>CLOB</code>, <code>DATALINK</code> or <code>JAVA_OBJECT</code>.
     * In this case, each element in the new
     * <code>SerialArray</code> object is the appropriate serialized form,
     * that is, a <code>SerialBlob</code>, <code>SerialClob</code>,
     * <code>SerialDatalink</code>, or <code>SerialJavaObject</code> object.
     * <P>
     * Note: (1) The <code>Array</code> object from which a <code>SerialArray</code>
     * object is created must have materialized the SQL <code>ARRAY</code> value's
     * data on the client before it is passed to the constructor.  Otherwise,
     * the new <code>SerialArray</code> object will contain no data.
     * <p>
     * Note: (2) The <code>Array</code> object supplied to this constructor cannot
     * return <code>null</code> for any <code>Array.getArray()</code> methods.
     * <code>SerialArray</code> cannot serialize <code>null</code> array values.
     *
     * @param array the <code>Array</code> object to be serialized
     * @throws SerialException if an error occurs serializing the
     *     <code>Array</code> object
     * @throws SQLException if a database access error occurs or the
     *     <i>array</i> parameter is <code>null</code>.
     */
     public SerialArray(Array array) throws SerialException, SQLException {
         if (array == null) {
             throw new SQLException("Cannot instantiate a SerialArray " +
                 "object with a null Array object");
         }

         if ((elements = (Object[])array.getArray()) == null) {
             throw new SQLException("Invalid Array object. Calls to Array.getArray() " +
                 "return null value which cannot be serialized");
         }

         //elements = (Object[])array.getArray();
         baseType = array.getBaseType();
         baseTypeName = array.getBaseTypeName();
         len = elements.length;

        switch (baseType) {

        case java.sql.Types.BLOB:
            for (int i = 0; i < len; i++) {
                elements[i] = new SerialBlob((Blob)elements[i]);
            }
            break;

        case java.sql.Types.CLOB:
            for (int i = 0; i < len; i++) {
                elements[i] = new SerialClob((Clob)elements[i]);
            }
            break;

        case java.sql.Types.DATALINK:
            for (int i = 0; i < len; i++) {
                elements[i] = new SerialDatalink((URL)elements[i]);
            }
            break;

        case java.sql.Types.JAVA_OBJECT:
            for (int i = 0; i < len; i++) {
                elements[i] = new SerialJavaObject((Object)elements[i]);
            }

        default:
            ;
        }


    }

        /**
         * Returns a new array that is a copy of this <code>SerialArray</code>
         * object.
         *
         * @return a copy of this <code>SerialArray</code> object as an
         *         <code>Object</code> in the Java programming language
         * @throws SerialException if an error occurs retrieving a copy of
     *         this <code>SerialArray</code> object
         */
    public Object getArray() throws SerialException {
        Object dst = new Object[len];
        System.arraycopy((Object)elements, 0, dst, 0, len);
        return dst;
    }

 //[if an error occurstype map used??]
        /**
         * Returns a new array that is a copy of this <code>SerialArray</code>
         * object, using the given type map for the custom
         * mapping of each element when the elements are SQL UDTs.
         * <P>
         * This method does custom mapping if the array elements are a UDT
         * and the given type map has an entry for that UDT.
     * Custom mapping is recursive,
         * meaning that if, for instance, an element of an SQL structured type
         * is an SQL structured type that itself has an element that is an SQL
         * structured type, each structured type that has a custom mapping will be
         * mapped according to the given type map.
         *
     * @param map a <code>java.util.Map</code> object in which
     *        each entry consists of 1) a <code>String</code> object
     *        giving the fully qualified name of a UDT and 2) the
     *        <code>Class</code> object for the <code>SQLData</code> implementation
     *        that defines how the UDT is to be mapped
         * @return a copy of this <code>SerialArray</code> object as an
         *         <code>Object</code> in the Java programming language
         * @throws SerialException if an error occurs
         */
    public Object getArray(Map<String, Class<?>> map) throws SerialException {
        Object dst[] = new Object[len];
        System.arraycopy((Object)elements, 0, dst, 0, len);
        return dst;
    }

        /**
         * Returns a new array that is a copy of a slice
         * of this <code>SerialArray</code> object, starting with the
         * element at the given index and containing the given number
         * of consecutive elements.
         *
         * @param index the index into this <code>SerialArray</code> object
         *              of the first element to be copied;
         *              the index of the first element is <code>0</code>
         * @param count the number of consecutive elements to be copied, starting
         *              at the given index
         * @return a copy of the designated elements in this <code>SerialArray</code>
         *         object as an <code>Object</code> in the Java programming language
         * @throws SerialException if an error occurs
         */
    public Object getArray(long index, int count) throws SerialException {
        Object dst = new Object[count];
        System.arraycopy((Object)elements, (int)index, dst, 0, count);
        return dst;
    }

        /**
         * Returns a new array that is a copy of a slice
         * of this <code>SerialArray</code> object, starting with the
         * element at the given index and containing the given number
         * of consecutive elements.
         * <P>
         * This method does custom mapping if the array elements are a UDT
         * and the given type map has an entry for that UDT.
     * Custom mapping is recursive,
         * meaning that if, for instance, an element of an SQL structured type
         * is an SQL structured type that itself has an element that is an SQL
         * structured type, each structured type that has a custom mapping will be
         * mapped according to the given type map.
         *
         * @param index the index into this <code>SerialArray</code> object
         *              of the first element to be copied; the index of the
         *              first element in the array is <code>0</code>
         * @param count the number of consecutive elements to be copied, starting
         *              at the given index
     * @param map a <code>java.util.Map</code> object in which
     *        each entry consists of 1) a <code>String</code> object
     *        giving the fully qualified name of a UDT and 2) the
     *        <code>Class</code> object for the <code>SQLData</code> implementation
     *        that defines how the UDT is to be mapped
         * @return a copy of the designated elements in this <code>SerialArray</code>
         *         object as an <code>Object</code> in the Java programming language
         * @throws SerialException if an error occurs
         */
    public Object getArray(long index, int count, Map<String,Class<?>> map)
        throws SerialException
    {
        Object dst = new Object[count];
        System.arraycopy((Object)elements, (int)index, dst, 0, count);
        return dst;
    }

        /**
         * Retrieves the SQL type of the elements in this <code>SerialArray</code>
         * object.  The <code>int</code> returned is one of the constants in the class
         * <code>java.sql.Types</code>.
         *
         * @return one of the constants in <code>java.sql.Types</code>, indicating
         *         the SQL type of the elements in this <code>SerialArray</code> object
         * @throws SerialException if an error occurs
         */
    public int getBaseType() throws SerialException {
        return baseType;
    }

        /**
         * Retrieves the DBMS-specific type name for the elements in this
         * <code>SerialArray</code> object.
         *
         * @return the SQL type name used by the DBMS for the base type of this
     *         <code>SerialArray</code> object
         * @throws SerialException if an error occurs
         */
    public String getBaseTypeName() throws SerialException {
        return baseTypeName;
    }

    /**
     * Retrieves a <code>ResultSet</code> object holding the elements of
     * the subarray that starts at
     * index <i>index</i> and contains up to <i>count</i> successive elements.
     * This method uses the connection's type map to map the elements of
     * the array if the map contains
     * an entry for the base type. Otherwise, the standard mapping is used.
     *
     * @param index the index into this <code>SerialArray</code> object
     *         of the first element to be copied; the index of the
     *         first element in the array is <code>0</code>
     * @param count the number of consecutive elements to be copied, starting
     *         at the given index
     * @return a <code>ResultSet</code> object containing the designated
     *         elements in this <code>SerialArray</code> object, with a
     *         separate row for each element
     * @throws SerialException, which in turn throws an
     *         <code>UnsupportedOperationException</code>, if this method is called
     */
    public ResultSet getResultSet(long index, int count) throws SerialException {
        throw new UnsupportedOperationException();
    }

    /**
     *
     * Retrieves a <code>ResultSet</code> object that contains all of
     * the elements of the SQL <code>ARRAY</code>
     * value represented by this <code>SerialArray</code> object. This method uses
     * the specified map for type map customizations unless the base type of the
     * array does not match a user-defined type (UDT) in <i>map</i>, in
     * which case it uses the
     * standard mapping. This version of the method <code>getResultSet</code>
     * uses either the given type map or the standard mapping; it never uses the
     * type map associated with the connection.
     *
     * @param map a <code>java.util.Map</code> object in which
     *        each entry consists of 1) a <code>String</code> object
     *        giving the fully qualified name of a UDT and 2) the
     *        <code>Class</code> object for the <code>SQLData</code> implementation
     *        that defines how the UDT is to be mapped
     * @return a <code>ResultSet</code> object containing all of the
     *         elements in this <code>SerialArray</code> object, with a
     *         separate row for each element
     * @throws SerialException, which in turn throws an
     *         <code>UnsupportedOperationException</code>, if this method is called
     */
    public ResultSet getResultSet(Map<String, Class<?>> map)
        throws SerialException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * Retrieves a <code>ResultSet</code> object that contains all of
     * the elements in the <code>ARRAY</code> value that this
     * <code>SerialArray</code> object represents.
     * If appropriate, the elements of the array are mapped using the connection's
     * type map; otherwise, the standard mapping is used.
     *
     * @return a <code>ResultSet</code> object containing all of the
     *         elements in this <code>SerialArray</code> object, with a
     *         separate row for each element
     * @throws SerialException if called, which in turn throws an
     *         <code>UnsupportedOperationException</code>, if this method is called
     */
    public ResultSet getResultSet() throws SerialException {
        throw new UnsupportedOperationException();
    }


    /**
     * Retrieves a result set holding the elements of the subarray that starts at
     * Retrieves a <code>ResultSet</code> object that contains a subarray of the
     * elements in this <code>SerialArray</code> object, starting at
     * index <i>index</i> and containing up to <i>count</i> successive
     * elements. This method uses
     * the specified map for type map customizations unless the base type of the
     * array does not match a user-defined type (UDT) in <i>map</i>, in
     * which case it uses the
     * standard mapping. This version of the method <code>getResultSet</code> uses
     * either the given type map or the standard mapping; it never uses the type
     * map associated with the connection.
     *
     * @param index the index into this <code>SerialArray</code> object
     *              of the first element to be copied; the index of the
     *              first element in the array is <code>0</code>
     * @param count the number of consecutive elements to be copied, starting
     *              at the given index
     * @param map a <code>java.util.Map</code> object in which
     *        each entry consists of 1) a <code>String</code> object
     *        giving the fully qualified name of a UDT and 2) the
     *        <code>Class</code> object for the <code>SQLData</code> implementation
     *        that defines how the UDT is to be mapped
     * @return a <code>ResultSet</code> object containing the designated
     *         elements in this <code>SerialArray</code> object, with a
     *         separate row for each element
     * @throws SerialException if called, which in turn throws an
     *         <code>UnsupportedOperationException</code>
     */
    public ResultSet getResultSet(long index, int count,
                                  Map<String,Class<?>> map)
        throws SerialException
    {
        throw new UnsupportedOperationException();
    }

    /**
     * The identifier that assists in the serialization of this <code>SerialArray</code>
     * object.
     */
    static final long serialVersionUID = -8466174297270688520L;
}
