/**************************************************************
 * 
 * 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_ucbhelper.hxx"

/**************************************************************************
								TODO
 **************************************************************************

 - This implementation is far away from completion. It has no interface
   for changes notifications etc.

 *************************************************************************/
#include <com/sun/star/ucb/ListActionType.hpp>
#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
#include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp>
#include <com/sun/star/ucb/XSourceInitialization.hpp>
#include <cppuhelper/interfacecontainer.hxx>
#include <ucbhelper/resultsethelper.hxx>

#include "osl/diagnose.h"

using namespace com::sun::star;

//=========================================================================
//=========================================================================
//
// ResultSetImplHelper Implementation.
//
//=========================================================================
//=========================================================================

namespace ucbhelper {

//=========================================================================
ResultSetImplHelper::ResultSetImplHelper(
    const uno::Reference< lang::XMultiServiceFactory >& rxSMgr )
: m_pDisposeEventListeners( 0 ),
  m_bStatic( sal_False ),
  m_bInitDone( sal_False ),
  m_xSMgr( rxSMgr )
{
}

//=========================================================================
ResultSetImplHelper::ResultSetImplHelper(
    const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
    const com::sun::star::ucb::OpenCommandArgument2& rCommand )
: m_pDisposeEventListeners( 0 ),
  m_bStatic( sal_False ),
  m_bInitDone( sal_False ),
  m_aCommand( rCommand ),
  m_xSMgr( rxSMgr )
{
}

//=========================================================================
// virtual
ResultSetImplHelper::~ResultSetImplHelper()
{
	delete m_pDisposeEventListeners;
}

//=========================================================================
//
// XInterface methods.
//
//=========================================================================

XINTERFACE_IMPL_4( ResultSetImplHelper,
				   lang::XTypeProvider,
				   lang::XServiceInfo,
				   lang::XComponent, /* base of XDynamicResultSet */
				   com::sun::star::ucb::XDynamicResultSet );

//=========================================================================
//
// XTypeProvider methods.
//
//=========================================================================

XTYPEPROVIDER_IMPL_3( ResultSetImplHelper,
					  lang::XTypeProvider,
				   	  lang::XServiceInfo,
					  com::sun::star::ucb::XDynamicResultSet );

//=========================================================================
//
// XServiceInfo methods.
//
//=========================================================================

XSERVICEINFO_NOFACTORY_IMPL_1( ResultSetImplHelper,
                               rtl::OUString::createFromAscii( 
                                   "ResultSetImplHelper" ),
                               rtl::OUString::createFromAscii( 
                                   DYNAMICRESULTSET_SERVICE_NAME ) );

//=========================================================================
//
// XComponent methods.
//
//=========================================================================

// virtual
void SAL_CALL ResultSetImplHelper::dispose()
	throw( uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );

	if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
	{
		lang::EventObject aEvt;
		aEvt.Source = static_cast< lang::XComponent * >( this );
		m_pDisposeEventListeners->disposeAndClear( aEvt );
	}
}

//=========================================================================
// virtual
void SAL_CALL ResultSetImplHelper::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 );
}

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

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

//=========================================================================
//
// XDynamicResultSet methods.
//
//=========================================================================

// virtual
uno::Reference< sdbc::XResultSet > SAL_CALL 
ResultSetImplHelper::getStaticResultSet()
	throw( com::sun::star::ucb::ListenerAlreadySetException,	
           uno::RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );

	if ( m_xListener.is() )
		throw com::sun::star::ucb::ListenerAlreadySetException();

	init( sal_True );
	return m_xResultSet1;
}

//=========================================================================
// virtual
void SAL_CALL ResultSetImplHelper::setListener(
        const uno::Reference< com::sun::star::ucb::XDynamicResultSetListener >&
            Listener )
	throw( com::sun::star::ucb::ListenerAlreadySetException,
           uno::RuntimeException )
{
	osl::ClearableMutexGuard aGuard( m_aMutex );

	if ( m_bStatic || m_xListener.is() )
		throw com::sun::star::ucb::ListenerAlreadySetException();

	m_xListener = Listener;

	//////////////////////////////////////////////////////////////////////
	// Create "welcome event" and send it to listener.
	//////////////////////////////////////////////////////////////////////

	// Note: We only have the implementation for a static result set at the
	//       moment (src590). The dynamic result sets passed to the listener
	//       are a fake. This implementation will never call "notify" at the
	//       listener to propagate any changes!!!

	init( sal_False );

	uno::Any aInfo;
	aInfo <<= com::sun::star::ucb::WelcomeDynamicResultSetStruct( 
        m_xResultSet1 /* "old" */,
        m_xResultSet2 /* "new" */ );

	uno::Sequence< com::sun::star::ucb::ListAction > aActions( 1 );
	aActions.getArray()[ 0 ] 
        = com::sun::star::ucb::ListAction( 
            0, // Position; not used
            0, // Count; not used
            com::sun::star::ucb::ListActionType::WELCOME,
            aInfo );
	aGuard.clear();

	Listener->notify(
        com::sun::star::ucb::ListEvent( 
            static_cast< cppu::OWeakObject * >( this ), aActions ) );
}

//=========================================================================
// virtual
sal_Int16 SAL_CALL ResultSetImplHelper::getCapabilities()
	throw( uno::RuntimeException )
{
	// ! com::sun::star::ucb::ContentResultSetCapability::SORTED
	return 0;
}

//=========================================================================
// virtual
void SAL_CALL ResultSetImplHelper::connectToCache(
        const uno::Reference< com::sun::star::ucb::XDynamicResultSet > & 
            xCache )
	throw( com::sun::star::ucb::ListenerAlreadySetException,
		   com::sun::star::ucb::AlreadyInitializedException,
		   com::sun::star::ucb::ServiceNotFoundException,
		   uno::RuntimeException )
{
	if ( m_xListener.is() )
		throw com::sun::star::ucb::ListenerAlreadySetException();

	if ( m_bStatic )
		throw com::sun::star::ucb::ListenerAlreadySetException();

	uno::Reference< com::sun::star::ucb::XSourceInitialization > 
        xTarget( xCache, uno::UNO_QUERY );
	if ( xTarget.is() )
	{
		uno::Reference< 
            com::sun::star::ucb::XCachedDynamicResultSetStubFactory > 
                xStubFactory;
		try
		{
			xStubFactory 
                = uno::Reference< 
                    com::sun::star::ucb::XCachedDynamicResultSetStubFactory >(
                        m_xSMgr->createInstance(
                            rtl::OUString::createFromAscii(
                                "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ),
				uno::UNO_QUERY );
		}
		catch ( uno::Exception const & )
		{
		}

		if ( xStubFactory.is() )
		{
			xStubFactory->connectToCache(
				  				this, xCache, m_aCommand.SortingInfo, 0 );
			return;
		}
	}
	throw com::sun::star::ucb::ServiceNotFoundException();
}

//=========================================================================
//
// Non-interface methods.
//
//=========================================================================

void ResultSetImplHelper::init( sal_Bool bStatic )
{
	osl::MutexGuard aGuard( m_aMutex );

	if ( !m_bInitDone )
	{
		if ( bStatic )
		{
			// virtual... derived class fills m_xResultSet1
			initStatic();

			OSL_ENSURE( m_xResultSet1.is(),
						"ResultSetImplHelper::init - No 1st result set!" );
			m_bStatic = sal_True;
		}
		else
		{
			// virtual... derived class fills m_xResultSet1 and m_xResultSet2
			initDynamic();

			OSL_ENSURE( m_xResultSet1.is(),
						"ResultSetImplHelper::init - No 1st result set!" );
			OSL_ENSURE( m_xResultSet2.is(),
						"ResultSetImplHelper::init - No 2nd result set!" );
			m_bStatic = sal_False;
		}
		m_bInitDone = sal_True;
	}
}

} // namespace ucbhelper