/**************************************************************
 *
 * 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_xmlhelp.hxx"
#include <ucbhelper/contentidentifier.hxx>
#include <com/sun/star/ucb/OpenMode.hpp>
#include <com/sun/star/uno/Reference.h>
#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBBUTE_HPP_
#include <com/sun/star/beans/PropertyAttribute.hpp>
#endif
#include <com/sun/star/ucb/ListActionType.hpp>
#include <com/sun/star/ucb/XSourceInitialization.hpp>
#include <ucbhelper/resultsetmetadata.hxx>

#include "resultsetbase.hxx"

using namespace chelp;
using namespace com::sun::star;

ResultSetBase::ResultSetBase( const uno::Reference< lang::XMultiServiceFactory >&  xMSF,
							  const uno::Reference< ucb::XContentProvider >&  xProvider,
							  sal_Int32 nOpenMode,
							  const uno::Sequence< beans::Property >& seq,
							  const uno::Sequence< ucb::NumberedSortingInfo >& seqSort )
	: m_xMSF( xMSF ),
	  m_xProvider( xProvider ),
	  m_nRow( -1 ),
	  m_nWasNull( true ),
	  m_nOpenMode( nOpenMode ),
	  m_bRowCountFinal( true ),
	  m_sProperty( seq ),
	  m_sSortingInfo( seqSort ),
	  m_pDisposeEventListeners( 0 ),
	  m_pRowCountListeners( 0 ),
	  m_pIsFinalListeners( 0 )
{
}

ResultSetBase::~ResultSetBase()
{
	delete m_pIsFinalListeners;
	delete m_pRowCountListeners;
	delete m_pDisposeEventListeners;
}


// XInterface

void SAL_CALL
ResultSetBase::acquire(
	void )
	throw()
{
	OWeakObject::acquire();
}


void SAL_CALL
ResultSetBase::release(
	void )
	throw()
{
	OWeakObject::release();
}



uno::Any SAL_CALL
ResultSetBase::queryInterface(
	const uno::Type& rType )
	throw( uno::RuntimeException )
{
	uno::Any aRet = cppu::queryInterface( rType,
										  SAL_STATIC_CAST( lang::XComponent*, this),
										  SAL_STATIC_CAST( sdbc::XRow*, this),
										  SAL_STATIC_CAST( sdbc::XResultSet*, this),
										  SAL_STATIC_CAST( sdbc::XResultSetMetaDataSupplier*, this),
										  SAL_STATIC_CAST( beans::XPropertySet*, this ),
										  SAL_STATIC_CAST( ucb::XContentAccess*, this) );
	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}



// XComponent


void SAL_CALL
ResultSetBase::addEventListener(
	const uno::Reference< lang::XEventListener >& Listener )
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );

	if ( ! m_pDisposeEventListeners )
		m_pDisposeEventListeners =
			new cppu::OInterfaceContainerHelper( m_aMutex );

	m_pDisposeEventListeners->addInterface( Listener );
}


void SAL_CALL
ResultSetBase::removeEventListener(
	const uno::Reference< lang::XEventListener >& Listener )
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );

	if ( m_pDisposeEventListeners )
		m_pDisposeEventListeners->removeInterface( Listener );
}



void SAL_CALL
ResultSetBase::dispose()
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );

	lang::EventObject aEvt;
	aEvt.Source = static_cast< lang::XComponent * >( this );

	if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
	{
		m_pDisposeEventListeners->disposeAndClear( aEvt );
	}
	if( m_pRowCountListeners && m_pRowCountListeners->getLength() )
	{
		m_pRowCountListeners->disposeAndClear( aEvt );
	}
	if( m_pIsFinalListeners && m_pIsFinalListeners->getLength() )
	{
		m_pIsFinalListeners->disposeAndClear( aEvt );
	}
}



//  XResultSet

sal_Bool SAL_CALL
ResultSetBase::next(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	sal_Bool test;
	m_nRow++;
	if( sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size() )
		test = true;
	else
		test = false;
	return test;
}


sal_Bool SAL_CALL
ResultSetBase::isBeforeFirst(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return m_nRow == -1;
}


sal_Bool SAL_CALL
ResultSetBase::isAfterLast(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return sal::static_int_cast<sal_uInt32>( m_nRow ) >= m_aItems.size();   // Cannot happen, if m_aFolder.isOpen()
}


sal_Bool SAL_CALL
ResultSetBase::isFirst(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return m_nRow == 0;
}


sal_Bool SAL_CALL
ResultSetBase::isLast(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	if( sal::static_int_cast<sal_uInt32>( m_nRow ) ==  m_aItems.size() - 1 )
		return true;
	else
		return false;
}


void SAL_CALL
ResultSetBase::beforeFirst(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	m_nRow = -1;
}


void SAL_CALL
ResultSetBase::afterLast(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	m_nRow = m_aItems.size();
}


sal_Bool SAL_CALL
ResultSetBase::first(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	m_nRow = -1;
	return next();
}


sal_Bool SAL_CALL
ResultSetBase::last(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	m_nRow = m_aItems.size() - 1;
	return true;
}


sal_Int32 SAL_CALL
ResultSetBase::getRow(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	// Test, whether behind last row
	if( -1 == m_nRow || sal::static_int_cast<sal_uInt32>( m_nRow ) >= m_aItems.size() )
		return 0;
	else
		return m_nRow+1;
}


sal_Bool SAL_CALL ResultSetBase::absolute( sal_Int32 row )
	throw( sdbc::SQLException, uno::RuntimeException)
{
	if( row >= 0 )
		m_nRow = row - 1;
	else
	{
		last();
		m_nRow += ( row + 1 );
		if( m_nRow < -1 )
			m_nRow = -1;
	}

	return 0<= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size();
}




sal_Bool SAL_CALL
ResultSetBase::relative(
	sal_Int32 row )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	if( isAfterLast() || isBeforeFirst() )
		throw sdbc::SQLException();

	if( row > 0 )
		while( row-- )
			next();
	else if( row < 0 )
		while( row++ && m_nRow > -1 )
			previous();

	return 0 <= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size();
}



sal_Bool SAL_CALL
ResultSetBase::previous(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
	if( sal::static_int_cast<sal_uInt32>( m_nRow ) > m_aItems.size() )
		m_nRow = m_aItems.size();  // Correct Handling of afterLast
	if( 0 <= m_nRow ) -- m_nRow;

	return 0 <= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size();
}


void SAL_CALL
ResultSetBase::refreshRow(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
}


sal_Bool SAL_CALL
ResultSetBase::rowUpdated(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return false;
}

sal_Bool SAL_CALL
ResultSetBase::rowInserted(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return false;
}

sal_Bool SAL_CALL
ResultSetBase::rowDeleted(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	return false;
}


uno::Reference< uno::XInterface > SAL_CALL
ResultSetBase::getStatement(
	void  )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	uno::Reference< uno::XInterface > test( 0 );
	return test;
}


// XCloseable

void SAL_CALL
ResultSetBase::close(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException)
{
}


rtl::OUString SAL_CALL
ResultSetBase::queryContentIdentifierString(
	void )
	throw( uno::RuntimeException )
{
	if( 0 <= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size() )
		return m_aPath[m_nRow];
	else
		return rtl::OUString();
}


uno::Reference< ucb::XContentIdentifier > SAL_CALL
ResultSetBase::queryContentIdentifier(
	void )
	throw( uno::RuntimeException )
{
	if( 0 <= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size() )
	{
		rtl::OUString url = queryContentIdentifierString();
		if( ! m_aIdents[m_nRow].is() && url.getLength() )
			m_aIdents[m_nRow] = uno::Reference< ucb::XContentIdentifier >(
                new ::ucbhelper::ContentIdentifier( m_xMSF,url ) );
		return m_aIdents[m_nRow];
	}

	return uno::Reference< ucb::XContentIdentifier >();
}


uno::Reference< ucb::XContent > SAL_CALL
ResultSetBase::queryContent(
	void )
	throw( uno::RuntimeException )
{
	if( 0 <= m_nRow && sal::static_int_cast<sal_uInt32>( m_nRow ) < m_aItems.size() )
		return m_xProvider->queryContent( queryContentIdentifier() );
	else
		return uno::Reference< ucb::XContent >();
}



class XPropertySetInfoImpl
    : public cppu::OWeakObject,
      public beans::XPropertySetInfo
{
public:

    XPropertySetInfoImpl( const uno::Sequence< beans::Property >& aSeq )
        : m_aSeq( aSeq )
    {
    }

    void SAL_CALL acquire( void )
        throw()
    {
        OWeakObject::acquire();
    }


    void SAL_CALL release( void )
        throw()
    {
        OWeakObject::release();
    }

    uno::Any SAL_CALL queryInterface( const uno::Type& rType )
        throw( uno::RuntimeException )
    {
        uno::Any aRet = cppu::queryInterface( rType,
                                              SAL_STATIC_CAST( beans::XPropertySetInfo*, this ) );
        return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
    }

    uno::Sequence< beans::Property > SAL_CALL getProperties()
        throw( uno::RuntimeException )
    {
        return m_aSeq;
    }

    beans::Property SAL_CALL getPropertyByName( const ::rtl::OUString& aName )
        throw( beans::UnknownPropertyException,
               uno::RuntimeException)
    {
        for( int i = 0; i < m_aSeq.getLength(); ++i )
            if( aName == m_aSeq[i].Name )
                return m_aSeq[i];
        throw beans::UnknownPropertyException();
    }

    sal_Bool SAL_CALL hasPropertyByName( const ::rtl::OUString& Name )
        throw( uno::RuntimeException )
    {
        for( int i = 0; i < m_aSeq.getLength(); ++i )
            if( Name == m_aSeq[i].Name )
                return true;
        return false;
    }

private:

    uno::Sequence< beans::Property > m_aSeq;
};



// XPropertySet
uno::Reference< beans::XPropertySetInfo > SAL_CALL
ResultSetBase::getPropertySetInfo()
	throw( uno::RuntimeException)
{
	uno::Sequence< beans::Property > seq(2);
	seq[0].Name = rtl::OUString::createFromAscii( "RowCount" );
	seq[0].Handle = -1;
	seq[0].Type = getCppuType( static_cast< sal_Int32* >(0) );
	seq[0].Attributes = beans::PropertyAttribute::READONLY;

	seq[1].Name = rtl::OUString::createFromAscii( "IsRowCountFinal" );
	seq[1].Handle = -1;
	seq[1].Type = getCppuType( static_cast< sal_Bool* >(0) );
	seq[1].Attributes = beans::PropertyAttribute::READONLY;

	//t
	return uno::Reference< beans::XPropertySetInfo > ( new XPropertySetInfoImpl( seq ) );
}



void SAL_CALL ResultSetBase::setPropertyValue(
	const rtl::OUString& aPropertyName, const uno::Any& aValue )
	throw( beans::UnknownPropertyException,
		   beans::PropertyVetoException,
		   lang::IllegalArgumentException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	(void)aValue;

	if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) ||
		aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) )
		return;

	throw beans::UnknownPropertyException();
}


uno::Any SAL_CALL ResultSetBase::getPropertyValue(
	const rtl::OUString& PropertyName )
	throw( beans::UnknownPropertyException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	if( PropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) )
	{
		uno::Any aAny;
		aAny <<= m_bRowCountFinal;
		return aAny;
	}
	else if ( PropertyName == rtl::OUString::createFromAscii( "RowCount" ) )
	{
		uno::Any aAny;
		sal_Int32 count = m_aItems.size();
		aAny <<= count;
		return aAny;
	}
	else
		throw beans::UnknownPropertyException();
}


void SAL_CALL ResultSetBase::addPropertyChangeListener(
	const rtl::OUString& aPropertyName,
	const uno::Reference< beans::XPropertyChangeListener >& xListener )
	throw( beans::UnknownPropertyException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) )
	{
		osl::MutexGuard aGuard( m_aMutex );
		if ( ! m_pIsFinalListeners )
			m_pIsFinalListeners =
				new cppu::OInterfaceContainerHelper( m_aMutex );

		m_pIsFinalListeners->addInterface( xListener );
	}
	else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) )
	{
		osl::MutexGuard aGuard( m_aMutex );
		if ( ! m_pRowCountListeners )
			m_pRowCountListeners =
				new cppu::OInterfaceContainerHelper( m_aMutex );
		m_pRowCountListeners->addInterface( xListener );
	}
	else
		throw beans::UnknownPropertyException();
}


void SAL_CALL ResultSetBase::removePropertyChangeListener(
	const rtl::OUString& aPropertyName,
	const uno::Reference< beans::XPropertyChangeListener >& aListener )
	throw( beans::UnknownPropertyException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	if( aPropertyName == rtl::OUString::createFromAscii( "IsRowCountFinal" ) &&
		m_pIsFinalListeners )
	{
		osl::MutexGuard aGuard( m_aMutex );
		m_pIsFinalListeners->removeInterface( aListener );
	}
	else if ( aPropertyName == rtl::OUString::createFromAscii( "RowCount" ) &&
			  m_pRowCountListeners )
	{
		osl::MutexGuard aGuard( m_aMutex );
		m_pRowCountListeners->removeInterface( aListener );
	}
	else
		throw beans::UnknownPropertyException();
}


void SAL_CALL ResultSetBase::addVetoableChangeListener(
	const rtl::OUString& PropertyName,
	const uno::Reference< beans::XVetoableChangeListener >& aListener )
	throw( beans::UnknownPropertyException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	(void)PropertyName;
	(void)aListener;
}


void SAL_CALL ResultSetBase::removeVetoableChangeListener(
	const rtl::OUString& PropertyName,
	const uno::Reference< beans::XVetoableChangeListener >& aListener )
	throw( beans::UnknownPropertyException,
		   lang::WrappedTargetException,
		   uno::RuntimeException)
{
	(void)PropertyName;
	(void)aListener;
}



// XResultSetMetaDataSupplier
uno::Reference< sdbc::XResultSetMetaData > SAL_CALL
ResultSetBase::getMetaData(
	void )
	throw( sdbc::SQLException,
		   uno::RuntimeException )
{
	::ucbhelper::ResultSetMetaData* p =
		  new ::ucbhelper::ResultSetMetaData(
			  m_xMSF, m_sProperty );
	return uno::Reference< sdbc::XResultSetMetaData >( p );
}
