/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "java/sql/Array.hxx"
#include "java/tools.hxx"
#include "java/sql/ResultSet.hxx"

using namespace connectivity;
//**************************************************************
//************ Class: java.sql.Array
//**************************************************************

jclass java_sql_Array::theClass = 0;

java_sql_Array::~java_sql_Array()
{}

jclass java_sql_Array::getMyClass() const
{
	// die Klasse muss nur einmal geholt werden, daher statisch
	if( !theClass )
        theClass = findMyClass("java/sql/Array");

	return theClass;
}

::rtl::OUString SAL_CALL java_sql_Array::getBaseTypeName(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    static jmethodID mID(NULL);
    return callStringMethod("getBaseTypeName",mID);
}

sal_Int32 SAL_CALL java_sql_Array::getBaseType(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    static jmethodID mID(NULL);
	return callIntMethod("getBaseType",mID);
}

::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > SAL_CALL java_sql_Array::getArray( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
	jobjectArray out(0);
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Environment been deleted!");

	{
		jobject obj = convertTypeMapToJavaMap(t.pEnv,typeMap);
		static const char * cSignature = "(Ljava/util/Map;)[Ljava/lang/Object;";
		static const char * cMethodName = "getArray";
        static jmethodID mID(NULL);
        obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
		// Java-Call absetzen
		out = (jobjectArray)t.pEnv->CallObjectMethod( object, mID, obj);
		ThrowSQLException(t.pEnv,*this);
		// und aufraeumen
		t.pEnv->DeleteLocalRef(obj);
	} //t.pEnv
	return ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >();//copyArrayAndDelete< ::com::sun::star::uno::Any,jobject>(t.pEnv,out);
}

::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > SAL_CALL java_sql_Array::getArrayAtIndex( sal_Int32 index, sal_Int32 count, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
	jobjectArray out(0);
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Environment been deleted!");

	{
		jobject obj = convertTypeMapToJavaMap(t.pEnv,typeMap);
		static const char * cSignature = "(IILjava/util/Map;)[Ljava/lang/Object;";
		static const char * cMethodName = "getArray";
		// Java-Call absetzen
		static jmethodID mID(NULL);
        obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
		out = (jobjectArray)t.pEnv->CallObjectMethod( object, mID, index,count,obj);
		ThrowSQLException(t.pEnv,*this);
		// und aufraeumen
		t.pEnv->DeleteLocalRef(obj);
	} //t.pEnv
	return ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >();//copyArrayAndDelete< ::com::sun::star::uno::Any,jobject>(t.pEnv,out);
}

::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL java_sql_Array::getResultSet( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
	jobject out(0);
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Environment been deleted!");
	{
		// Parameter konvertieren
		jobject obj = convertTypeMapToJavaMap(t.pEnv,typeMap);
		// temporaere Variable initialisieren
		static const char * cSignature = "(Ljava/util/Map;)Ljava/sql/ResultSet;";
		static const char * cMethodName = "getResultSet";
		// Java-Call absetzen
		static jmethodID mID(NULL);
        obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
		out = t.pEnv->CallObjectMethod( object, mID, obj);
		ThrowSQLException(t.pEnv,*this);
		// und aufraeumen
		t.pEnv->DeleteLocalRef(obj);
	} //t.pEnv
	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
	//	return out==0 ? 0 : new java_sql_ResultSet( t.pEnv, out );
	return NULL;
}

::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL java_sql_Array::getResultSetAtIndex( sal_Int32 index, sal_Int32 count, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
	jobject out(0);
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Environment been deleted!");
	{
		// Parameter konvertieren
		jobject obj = convertTypeMapToJavaMap(t.pEnv,typeMap);
		// temporaere Variable initialisieren
		static const char * cSignature = "(Ljava/util/Map;)Ljava/sql/ResultSet;";
		static const char * cMethodName = "getResultSetAtIndex";
		// Java-Call absetzen
		static jmethodID mID(NULL);
        obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
		out = t.pEnv->CallObjectMethod( object, mID, index,count,obj);
		ThrowSQLException(t.pEnv,*this);
		// und aufraeumen
		t.pEnv->DeleteLocalRef(obj);
	} //t.pEnv
	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
	//	return out==0 ? 0 : new java_sql_ResultSet( t.pEnv, out );
	return NULL;
}
