diff options
Diffstat (limited to 'ucb/source/sorter')
-rw-r--r-- | ucb/source/sorter/makefile.mk | 71 | ||||
-rw-r--r-- | ucb/source/sorter/sortdynres.cxx | 628 | ||||
-rw-r--r-- | ucb/source/sorter/sortdynres.hxx | 257 | ||||
-rw-r--r-- | ucb/source/sorter/sortmain.cxx | 75 | ||||
-rw-r--r-- | ucb/source/sorter/sortresult.cxx | 2070 | ||||
-rw-r--r-- | ucb/source/sorter/sortresult.hxx | 455 | ||||
-rw-r--r-- | ucb/source/sorter/srtrs.xml | 66 | ||||
-rw-r--r-- | ucb/source/sorter/srtrs1.component | 34 |
8 files changed, 3656 insertions, 0 deletions
diff --git a/ucb/source/sorter/makefile.mk b/ucb/source/sorter/makefile.mk new file mode 100644 index 000000000000..008e39b4bce3 --- /dev/null +++ b/ucb/source/sorter/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=ucb +TARGET=srtrs +ENABLE_EXCEPTIONS=TRUE + +# Version +UCB_MAJOR=1 + +.INCLUDE: settings.mk +.IF "$(L10N_framework)"=="" + +SLOFILES=\ + $(SLO)$/sortdynres.obj \ + $(SLO)$/sortresult.obj \ + $(SLO)$/sortmain.obj + +LIB1TARGET=$(SLB)$/_$(TARGET).lib +LIB1OBJFILES=$(SLOFILES) + +SHL1TARGET=$(TARGET)$(UCB_MAJOR) +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1LIBS=$(LIB1TARGET) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +DEF1NAME=$(SHL1TARGET) +.ENDIF # L10N_framework + +.INCLUDE: target.mk + + +ALLTAR : $(MISC)/srtrs1.component + +$(MISC)/srtrs1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + srtrs1.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt srtrs1.component diff --git a/ucb/source/sorter/sortdynres.cxx b/ucb/source/sorter/sortdynres.cxx new file mode 100644 index 000000000000..2fc38ee46a42 --- /dev/null +++ b/ucb/source/sorter/sortdynres.cxx @@ -0,0 +1,628 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <vector> +#include <sortdynres.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/ucb/ContentResultSetCapability.hpp> +#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> + +//----------------------------------------------------------------------------- +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace rtl; + +//========================================================================= + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex* pMutex = NULL; + if( !pMutex ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pMutex ) + { + static osl::Mutex aMutex; + pMutex = &aMutex; + } + } + + return *pMutex; +} + +//========================================================================= +// +// SortedDynamicResultSet +// +//========================================================================= + +SortedDynamicResultSet::SortedDynamicResultSet( + const Reference < XDynamicResultSet > &xOriginal, + const Sequence < NumberedSortingInfo > &aOptions, + const Reference < XAnyCompareFactory > &xCompFac, + const Reference < XMultiServiceFactory > &xSMgr ) +{ + mpDisposeEventListeners = NULL; + mpOwnListener = new SortedDynamicResultSetListener( this ); + + mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener ); + + mxOriginal = xOriginal; + maOptions = aOptions; + mxCompFac = xCompFac; + mxSMgr = xSMgr; + + mpOne = NULL; + mpTwo = NULL; + + mbGotWelcome = sal_False; + mbUseOne = sal_True; + mbStatic = sal_False; +} + +//-------------------------------------------------------------------------- +SortedDynamicResultSet::~SortedDynamicResultSet() +{ + mpOwnListener->impl_OwnerDies(); + mxOwnListener.clear(); + + delete mpDisposeEventListeners; + + mxOne.clear(); + mxTwo.clear(); + mxOriginal.clear(); + + mpOne = NULL; + mpTwo = NULL; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_4( SortedDynamicResultSet, + XTypeProvider, + XServiceInfo, + XComponent, /* base class of XDynamicResultSet */ + XDynamicResultSet ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet, + XTypeProvider, + XServiceInfo, + XDynamicResultSet ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedDynamicResultSet" ), + OUString::createFromAscii( + DYNAMIC_RESULTSET_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::dispose() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + mpDisposeEventListeners->disposeAndClear( aEvt ); + } + + mxOne.clear(); + mxTwo.clear(); + mxOriginal.clear(); + + mpOne = NULL; + mpTwo = NULL; + mbUseOne = sal_True; +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::addEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners = + new OInterfaceContainerHelper( getContainerMutex() ); + + mpDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedDynamicResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// XDynamicResultSet methods. +// ------------------------------------------------------------------------------ +Reference< XResultSet > SAL_CALL +SortedDynamicResultSet::getStaticResultSet() + throw( ListenerAlreadySetException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + mbStatic = sal_True; + + if ( mxOriginal.is() ) + { + mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() ); + mxOne = mpOne; + mpOne->Initialize( maOptions, mxCompFac ); + } + + return mxOne; +} + +// ------------------------------------------------------------------------------ +void SAL_CALL +SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener ) + throw( ListenerAlreadySetException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + addEventListener( Reference< XEventListener >::query( Listener ) ); + + mxListener = Listener; + + if ( mxOriginal.is() ) + mxOriginal->setListener( mxOwnListener ); +} + +// ------------------------------------------------------------------------------ +void SAL_CALL +SortedDynamicResultSet::connectToCache( + const Reference< XDynamicResultSet > & xCache ) + throw( ListenerAlreadySetException, + AlreadyInitializedException, + ServiceNotFoundException, + RuntimeException ) +{ + if( mxListener.is() ) + throw ListenerAlreadySetException(); + + if( mbStatic ) + throw ListenerAlreadySetException(); + + Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); + if( xTarget.is() && mxSMgr.is() ) + { + Reference< XCachedDynamicResultSetStubFactory > xStubFactory; + try + { + xStubFactory = Reference< XCachedDynamicResultSetStubFactory >( + mxSMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), + UNO_QUERY ); + } + catch ( Exception const & ) + { + } + + if( xStubFactory.is() ) + { + xStubFactory->connectToCache( + this, xCache, Sequence< NumberedSortingInfo > (), NULL ); + return; + } + } + throw ServiceNotFoundException(); +} + +// ------------------------------------------------------------------------------ +sal_Int16 SAL_CALL +SortedDynamicResultSet::getCapabilities() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Int16 nCaps = 0; + + if ( mxOriginal.is() ) + nCaps = mxOriginal->getCapabilities(); + + nCaps |= ContentResultSetCapability::SORTED; + + return nCaps; +} + +//-------------------------------------------------------------------------- +// XDynamicResultSetListener methods. +// ------------------------------------------------------------------------------ + +/** In the first notify-call the listener gets the two + <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s + are implementations of the service <type>ContentResultSet</type>. + + <p>The notified new <type>XResultSet</type> will stay valid after returning + notification. The old one will become invalid after returning notification. + + <p>While in notify-call the listener is allowed to read old and new version, + except in the first call, where only the new Resultset is valid. + + <p>The Listener is allowed to blockade this call, until he really want to go + to the new version. The only situation, where the listener has to return the + update call at once is, while he disposes his broadcaster or while he is + removing himsef as listener (otherwise you deadlock)!!! +*/ +void SAL_CALL +SortedDynamicResultSet::impl_notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Bool bHasNew = sal_False; + sal_Bool bHasModified = sal_False; + + SortedResultSet *pCurSet = NULL; + + // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old + // nach New kopieren + if ( mbGotWelcome ) + { + if ( mbUseOne ) + { + mbUseOne = sal_False; + mpTwo->CopyData( mpOne ); + pCurSet = mpTwo; + } + else + { + mbUseOne = sal_True; + mpOne->CopyData( mpTwo ); + pCurSet = mpOne; + } + } + + Any aRet; + + try { + aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) ); + } + catch ( UnknownPropertyException ) {} + catch ( WrappedTargetException ) {} + + long nOldCount = pCurSet->GetCount(); + sal_Bool bWasFinal = false; + + aRet >>= bWasFinal; + + // handle the actions in the list + for ( long i=0; i<Changes.Changes.getLength(); i++ ) + { + const ListAction aAction = Changes.Changes[i]; + switch ( aAction.ListActionType ) + { + case ListActionType::WELCOME: + { + WelcomeDynamicResultSetStruct aWelcome; + if ( aAction.ActionInfo >>= aWelcome ) + { + mpTwo = new SortedResultSet( aWelcome.Old ); + mxTwo = mpTwo; + mpOne = new SortedResultSet( aWelcome.New ); + mxOne = mpOne; + mpOne->Initialize( maOptions, mxCompFac ); + mbGotWelcome = sal_True; + mbUseOne = sal_True; + pCurSet = mpOne; + + aWelcome.Old = mxTwo; + aWelcome.New = mxOne; + + ListAction *pWelcomeAction = new ListAction; + pWelcomeAction->ActionInfo <<= aWelcome; + pWelcomeAction->Position = 0; + pWelcomeAction->Count = 0; + pWelcomeAction->ListActionType = ListActionType::WELCOME; + + maActions.Insert( pWelcomeAction ); + } + else + { + // throw RuntimeException(); + } + break; + } + case ListActionType::INSERTED: + { + pCurSet->InsertNew( aAction.Position, aAction.Count ); + bHasNew = sal_True; + break; + } + case ListActionType::REMOVED: + { + pCurSet->Remove( aAction.Position, + aAction.Count, + &maActions ); + break; + } + case ListActionType::MOVED: + { + long nOffset = 0; + if ( aAction.ActionInfo >>= nOffset ) + { + pCurSet->Move( aAction.Position, + aAction.Count, + nOffset ); + } + break; + } + case ListActionType::PROPERTIES_CHANGED: + { + pCurSet->SetChanged( aAction.Position, aAction.Count ); + bHasModified = sal_True; + break; + } + default: break; + } + } + + if ( bHasModified ) + pCurSet->ResortModified( &maActions ); + + if ( bHasNew ) + pCurSet->ResortNew( &maActions ); + + // send the new actions with a notify to the listeners + SendNotify(); + + // check for propertyChangeEvents + pCurSet->CheckProperties( nOldCount, bWasFinal ); +} + +//----------------------------------------------------------------- +// XEventListener +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSet::impl_disposing( const EventObject& ) + throw( RuntimeException ) +{ + mxListener.clear(); + mxOriginal.clear(); +} + +// ------------------------------------------------------------------------------ +// private methods +// ------------------------------------------------------------------------------ +void SortedDynamicResultSet::SendNotify() +{ + long nCount = maActions.Count(); + + if ( nCount && mxListener.is() ) + { + Sequence< ListAction > aActionList( maActions.Count() ); + ListAction *pActionList = aActionList.getArray(); + + for ( long i=0; i<nCount; i++ ) + { + pActionList[ i ] = *(maActions.GetAction( i )); + } + + ListEvent aNewEvent; + aNewEvent.Changes = aActionList; + + mxListener->notify( aNewEvent ); + } + + // clean up + maActions.Clear(); +} + +//========================================================================= +// +// SortedDynamicResultSetFactory +// +//========================================================================= +SortedDynamicResultSetFactory::SortedDynamicResultSetFactory( + const Reference< XMultiServiceFactory > & rSMgr ) +{ + mxSMgr = rSMgr; +} + +//-------------------------------------------------------------------------- +SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory() +{ +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_3( SortedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XSortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory, + XTypeProvider, + XServiceInfo, + XSortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ), + OUString::createFromAscii( + DYNAMIC_RESULTSET_FACTORY_NAME ) ); + +//-------------------------------------------------------------------------- +// Service factory implementation. +//-------------------------------------------------------------------------- + +ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory ); + +//-------------------------------------------------------------------------- +// SortedDynamicResultSetFactory methods. +//-------------------------------------------------------------------------- +Reference< XDynamicResultSet > SAL_CALL +SortedDynamicResultSetFactory::createSortedDynamicResultSet( + const Reference< XDynamicResultSet > & Source, + const Sequence< NumberedSortingInfo > & Info, + const Reference< XAnyCompareFactory > & CompareFactory ) + throw( RuntimeException ) +{ + Reference< XDynamicResultSet > xRet; + xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr ); + return xRet; +} + +//========================================================================= +// +// EventList +// +//========================================================================= + +void EventList::Clear() +{ + for ( std::deque< LISTACTION* >::size_type i = 0; + i < maData.size(); ++i ) + { + delete maData[i]; + } + + maData.clear(); +} + +//-------------------------------------------------------------------------- +void EventList::AddEvent( long nType, long nPos, long nCount ) +{ + ListAction *pAction = new ListAction; + pAction->Position = nPos; + pAction->Count = nCount; + pAction->ListActionType = nType; + + Insert( pAction ); +} + +//================================================================= +// +// SortedDynamicResultSetListener +// +//================================================================= + +SortedDynamicResultSetListener::SortedDynamicResultSetListener( + SortedDynamicResultSet *mOwner ) +{ + mpOwner = mOwner; +} + +//----------------------------------------------------------------- +SortedDynamicResultSetListener::~SortedDynamicResultSetListener() +{ +} + +//----------------------------------------------------------------- +// XInterface methods. +//----------------------------------------------------------------- + +XINTERFACE_IMPL_2( SortedDynamicResultSetListener, + XEventListener, /* base class of XDynamicResultSetListener */ + XDynamicResultSetListener ); + +//----------------------------------------------------------------- +// XEventListener ( base of XDynamicResultSetListener ) +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::disposing( const EventObject& Source ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_disposing( Source ); +} + +//----------------------------------------------------------------- +// XDynamicResultSetListener +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::notify( const ListEvent& Changes ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_notify( Changes ); +} + +//----------------------------------------------------------------- +// own methods: +//----------------------------------------------------------------- +void SAL_CALL +SortedDynamicResultSetListener::impl_OwnerDies() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mpOwner = NULL; +} + diff --git a/ucb/source/sorter/sortdynres.hxx b/ucb/source/sorter/sortdynres.hxx new file mode 100644 index 000000000000..fe026d40a3f7 --- /dev/null +++ b/ucb/source/sorter/sortdynres.hxx @@ -0,0 +1,257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SORTDYNRES_HXX +#define _SORTDYNRES_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/ucb/XDynamicResultSet.hpp> +#include <com/sun/star/ucb/XDynamicResultSetListener.hpp> +#include <com/sun/star/ucb/ListenerAlreadySetException.hpp> +#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> +#include <ucbhelper/macros.hxx> +#include "sortresult.hxx" + +namespace cppu { + class OInterfaceContainerHelper; +} + +//----------------------------------------------------------------------------- + +#define NUMBERED_SORTINGINFO com::sun::star::ucb::NumberedSortingInfo +#define RUNTIMEEXCEPTION com::sun::star::uno::RuntimeException +#define REFERENCE com::sun::star::uno::Reference +#define SEQUENCE com::sun::star::uno::Sequence +#define EVENTOBJECT com::sun::star::lang::EventObject +#define XEVENTLISTENER com::sun::star::lang::XEventListener +#define XMULTISERVICEFACTORY com::sun::star::lang::XMultiServiceFactory +#define XRESULTSET com::sun::star::sdbc::XResultSet +#define SQLEXCEPTION com::sun::star::sdbc::SQLException +#define XANYCOMPAREFACTORY com::sun::star::ucb::XAnyCompareFactory +#define XDYNAMICRESULTSET com::sun::star::ucb::XDynamicResultSet +#define XDYNAMICRESULTSETLISTENER com::sun::star::ucb::XDynamicResultSetListener +#define LISTENERALREADYSETEXCEPTION com::sun::star::ucb::ListenerAlreadySetException + +#define DYNAMIC_RESULTSET_SERVICE_NAME "com.sun.star.ucb.SortedDynamicResultSet" +#define DYNAMIC_RESULTSET_FACTORY_NAME "com.sun.star.ucb.SortedDynamicResultSetFactory" + +//----------------------------------------------------------------------------- +class SortedDynamicResultSetListener; + +class SortedDynamicResultSet: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XDynamicResultSet +{ + cppu::OInterfaceContainerHelper *mpDisposeEventListeners; + + REFERENCE < XDYNAMICRESULTSETLISTENER > mxListener; + REFERENCE < XDYNAMICRESULTSETLISTENER > mxOwnListener; + + REFERENCE < XRESULTSET > mxOne; + REFERENCE < XRESULTSET > mxTwo; + REFERENCE < XDYNAMICRESULTSET > mxOriginal; + SEQUENCE < NUMBERED_SORTINGINFO > maOptions; + REFERENCE < XANYCOMPAREFACTORY > mxCompFac; + REFERENCE < XMULTISERVICEFACTORY > mxSMgr; + + SortedResultSet* mpOne; + SortedResultSet* mpTwo; + SortedDynamicResultSetListener* mpOwnListener; + + EventList maActions; + osl::Mutex maMutex; + sal_Bool mbGotWelcome :1; + sal_Bool mbUseOne :1; + sal_Bool mbStatic :1; + +private: + + void SendNotify(); + +public: + SortedDynamicResultSet( const REFERENCE < XDYNAMICRESULTSET > &xOriginal, + const SEQUENCE < NUMBERED_SORTINGINFO > &aOptions, + const REFERENCE < XANYCOMPAREFACTORY > &xCompFac, + const REFERENCE < XMULTISERVICEFACTORY > &xSMgr ); + + ~SortedDynamicResultSet(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_NOFACTORY_DECL() + + //----------------------------------------------------------------- + // XComponent + //----------------------------------------------------------------- + virtual void SAL_CALL + dispose() throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + //----------------------------------------------------------------- + // XDynamicResultSet + //----------------------------------------------------------------- + virtual REFERENCE< XRESULTSET > SAL_CALL + getStaticResultSet( ) + throw( LISTENERALREADYSETEXCEPTION, RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + setListener( const REFERENCE< XDYNAMICRESULTSETLISTENER >& Listener ) + throw( LISTENERALREADYSETEXCEPTION, RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + connectToCache( const REFERENCE< XDYNAMICRESULTSET > & xCache ) + throw( LISTENERALREADYSETEXCEPTION, + com::sun::star::ucb::AlreadyInitializedException, + com::sun::star::ucb::ServiceNotFoundException, + RUNTIMEEXCEPTION ); + + virtual sal_Int16 SAL_CALL + getCapabilities() + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // own methods: + //----------------------------------------------------------------- + virtual void SAL_CALL + impl_disposing( const EVENTOBJECT& Source ) + throw( RUNTIMEEXCEPTION ); + + virtual void SAL_CALL + impl_notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( RUNTIMEEXCEPTION ); +}; + +//----------------------------------------------------------------------------- + +class SortedDynamicResultSetListener: + public cppu::OWeakObject, + public com::sun::star::ucb::XDynamicResultSetListener +{ + SortedDynamicResultSet *mpOwner; + osl::Mutex maMutex; + +public: + SortedDynamicResultSetListener( SortedDynamicResultSet *mOwner ); + ~SortedDynamicResultSetListener(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XEventListener ( base of XDynamicResultSetListener ) + //----------------------------------------------------------------- + virtual void SAL_CALL + disposing( const EVENTOBJECT& Source ) + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // XDynamicResultSetListener + //----------------------------------------------------------------- + virtual void SAL_CALL + notify( const ::com::sun::star::ucb::ListEvent& Changes ) + throw( RUNTIMEEXCEPTION ); + + //----------------------------------------------------------------- + // own methods: + //----------------------------------------------------------------- + void SAL_CALL impl_OwnerDies(); +}; + +//----------------------------------------------------------------------------- + +class SortedDynamicResultSetFactory: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::ucb::XSortedDynamicResultSetFactory +{ + + REFERENCE< XMULTISERVICEFACTORY > mxSMgr; + +public: + + SortedDynamicResultSetFactory( + const REFERENCE< XMULTISERVICEFACTORY > & rSMgr); + + ~SortedDynamicResultSetFactory(); + + //----------------------------------------------------------------- + // XInterface + //----------------------------------------------------------------- + XINTERFACE_DECL() + + //----------------------------------------------------------------- + // XTypeProvider + //----------------------------------------------------------------- + XTYPEPROVIDER_DECL() + + //----------------------------------------------------------------- + // XServiceInfo + //----------------------------------------------------------------- + XSERVICEINFO_DECL() + + //----------------------------------------------------------------- + // XSortedDynamicResultSetFactory + + virtual REFERENCE< XDYNAMICRESULTSET > SAL_CALL + createSortedDynamicResultSet( + const REFERENCE< XDYNAMICRESULTSET > & Source, + const SEQUENCE< NUMBERED_SORTINGINFO > & Info, + const REFERENCE< XANYCOMPAREFACTORY > & CompareFactory ) + throw( RUNTIMEEXCEPTION ); +}; + +#endif diff --git a/ucb/source/sorter/sortmain.cxx b/ucb/source/sorter/sortmain.cxx new file mode 100644 index 000000000000..5ad9a529e1f2 --- /dev/null +++ b/ucb/source/sorter/sortmain.cxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" +#include <sortdynres.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +//========================================================================= +extern "C" void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//========================================================================= +extern "C" void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + Reference< XMultiServiceFactory > xSMgr( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ) ); + Reference< XSingleServiceFactory > xFactory; + + ////////////////////////////////////////////////////////////////////// + // SortedDynamicResultSetFactory. + ////////////////////////////////////////////////////////////////////// + + if ( SortedDynamicResultSetFactory::getImplementationName_Static(). + compareToAscii( pImplName ) == 0 ) + { + xFactory = SortedDynamicResultSetFactory::createServiceFactory( xSMgr ); + } + + ////////////////////////////////////////////////////////////////////// + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + + return pRet; +} + diff --git a/ucb/source/sorter/sortresult.cxx b/ucb/source/sorter/sortresult.cxx new file mode 100644 index 000000000000..6e546950a23a --- /dev/null +++ b/ucb/source/sorter/sortresult.cxx @@ -0,0 +1,2070 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <vector> +#include <sortresult.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/XAnyCompare.hpp> +#include <com/sun/star/ucb/XAnyCompareFactory.hpp> +#include <osl/diagnose.h> + +//----------------------------------------------------------------------------- +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::io; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::ucb; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +using namespace cppu; +using namespace rtl; + +//========================================================================= + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex* pMutex = NULL; + if( !pMutex ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pMutex ) + { + static osl::Mutex aMutex; + pMutex = &aMutex; + } + } + + return *pMutex; +} + +//========================================================================== + +struct SortInfo +{ + sal_Bool mbUseOwnCompare; + sal_Bool mbAscending; + sal_Bool mbCaseSensitive; + sal_Int32 mnColumn; + sal_Int32 mnType; + SortInfo* mpNext; + Reference < XAnyCompare > mxCompareFunction; +}; + +//----------------------------------------------------------------------------- + +struct SortListData +{ + sal_Bool mbModified; + long mnCurPos; + long mnOldPos; + + SortListData( long nPos, sal_Bool bModified = sal_False ); +}; + +//============================================================================ +// +// class SRSPropertySetInfo. +// +//============================================================================ + +class SRSPropertySetInfo : + public OWeakObject, + public XTypeProvider, + public XPropertySetInfo +{ + Property maProps[2]; + +private: + +public: + SRSPropertySetInfo(); + virtual ~SRSPropertySetInfo(); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties() + throw( RuntimeException ); + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) + throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) + throw( RuntimeException ); +}; + +//========================================================================= +// +// PropertyChangeListenerContainer_Impl. +// +//========================================================================= + +struct equalStr_Impl +{ + bool operator()( const OUString& s1, const OUString& s2 ) const + { + return !!( s1 == s2 ); + } +}; + +struct hashStr_Impl +{ + size_t operator()( const OUString& rName ) const + { + return rName.hashCode(); + } +}; + +typedef OMultiTypeInterfaceContainerHelperVar +< + OUString, + hashStr_Impl, + equalStr_Impl +> PropertyChangeListenerContainer_Impl; + +//========================================================================= +// +// class PropertyChangeListeners_Impl +// +//========================================================================= + +class PropertyChangeListeners_Impl : public PropertyChangeListenerContainer_Impl +{ +public: + PropertyChangeListeners_Impl() + : PropertyChangeListenerContainer_Impl( getContainerMutex() ) {} +}; + +//========================================================================== +SortedResultSet::SortedResultSet( Reference< XResultSet > aResult ) +{ + mpDisposeEventListeners = NULL; + mpPropChangeListeners = NULL; + mpVetoChangeListeners = NULL; + mpPropSetInfo = NULL; + + mxOriginal = aResult; + mpSortInfo = NULL; + mnLastSort = 0; + mnCurEntry = 0; + mnCount = 0; + mbIsCopy = sal_False; +} + +//-------------------------------------------------------------------------- +SortedResultSet::~SortedResultSet() +{ + mxOriginal.clear(); + mxOther.clear(); + + if ( !mbIsCopy ) + { + SortInfo *pInfo = mpSortInfo; + while ( pInfo ) + { + mpSortInfo = pInfo->mpNext; + delete pInfo; + pInfo = mpSortInfo; + } + } + + mpSortInfo = NULL; + + if ( mpPropSetInfo ) + mpPropSetInfo->release(); + + delete mpPropChangeListeners; + delete mpVetoChangeListeners; +} + +//-------------------------------------------------------------------------- +// XInterface methods. +//-------------------------------------------------------------------------- + +XINTERFACE_IMPL_9( SortedResultSet, + XTypeProvider, + XServiceInfo, + XComponent, + XContentAccess, + XResultSet, + XRow, + XCloseable, + XResultSetMetaDataSupplier, + XPropertySet ); + +//-------------------------------------------------------------------------- +// XTypeProvider methods. +//-------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_9( SortedResultSet, + XTypeProvider, + XServiceInfo, + XComponent, + XContentAccess, + XResultSet, + XRow, + XCloseable, + XResultSetMetaDataSupplier, + XPropertySet ); + +//-------------------------------------------------------------------------- +// XServiceInfo methods. +//-------------------------------------------------------------------------- + +XSERVICEINFO_NOFACTORY_IMPL_1( SortedResultSet, + OUString::createFromAscii( + "com.sun.star.comp.ucb.SortedResultSet" ), + OUString::createFromAscii( + RESULTSET_SERVICE_NAME ) ); + +//-------------------------------------------------------------------------- +// XComponent methods. +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::dispose() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() ) + { + EventObject aEvt; + aEvt.Source = static_cast< XComponent * >( this ); + mpDisposeEventListeners->disposeAndClear( aEvt ); + } + + if ( mpPropChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + mpPropChangeListeners->disposeAndClear( aEvt ); + } + + if ( mpVetoChangeListeners ) + { + EventObject aEvt; + aEvt.Source = static_cast< XPropertySet * >( this ); + mpVetoChangeListeners->disposeAndClear( aEvt ); + } + + mxOriginal.clear(); + mxOther.clear(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners = + new OInterfaceContainerHelper( getContainerMutex() ); + + mpDisposeEventListeners->addInterface( Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + +//-------------------------------------------------------------------------- +// XContentAccess methods. +//-------------------------------------------------------------------------- + +OUString SAL_CALL +SortedResultSet::queryContentIdentifierString() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifierString(); +} + +//-------------------------------------------------------------------------- +Reference< XContentIdentifier > SAL_CALL +SortedResultSet::queryContentIdentifier() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifier(); +} + +//-------------------------------------------------------------------------- +Reference< XContent > SAL_CALL +SortedResultSet::queryContent() + throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContent(); +} + + +//-------------------------------------------------------------------------- +// XResultSet methods. +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::next() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + mnCurEntry++; + + if ( mnCurEntry > 0 ) + { + if ( mnCurEntry <= mnCount ) + { + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = mnCount + 1; + } + } + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isBeforeFirst() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry ) + return sal_False; + else + return sal_True; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isAfterLast() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry > mnCount ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isFirst() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry == 1 ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::isLast() + throw ( SQLException, RuntimeException ) +{ + if ( mnCurEntry == mnCount ) + return sal_True; + else + return sal_False; +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::beforeFirst() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = 0; + mxOriginal->beforeFirst(); +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::afterLast() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = mnCount+1; + mxOriginal->afterLast(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::first() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = 1; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::last() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = mnCount; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } +} + +//------------------------------------------------------------------------- +sal_Int32 SAL_CALL SortedResultSet::getRow() + throw ( SQLException, RuntimeException ) +{ + return mnCurEntry; +} + +//------------------------------------------------------------------------- +/** + moves the cursor to the given row number in the result set. + <p>If the row number is positive, the cursor moves to the given row + number with respect to the beginning of the result set. The first + row is row 1, the second is row 2, and so on. + <p>If the given row number is negative, the cursor moves to an + absolute row position with respect to the end of the result set. + For example, calling <code>moveToPosition(-1)</code> positions the + cursor on the last row, <code>moveToPosition(-2)</code> indicates the + next-to-last row, and so on. + <p>An attempt to position the cursor beyond the first/last row in the + result set leaves the cursor before/after the first/last row, + respectively. + <p>Note: Calling <code>moveToPosition(1)</code> is the same + as calling <code>moveToFirst()</code>. Calling + <code>moveToPosition(-1)</code> is the same as calling + <code>moveToLast()</code>. + @param row + is the number of rows to move. Could be negative. + @returns + <sal_True/> if the cursor is on a row; <sal_False/> otherwise + @throws SQLException + if a database access error occurs or if row is 0, or the result set + type is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::absolute( sal_Int32 row ) + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + sal_Int32 nIndex; + + if ( row > 0 ) + { + if ( row <= mnCount ) + { + mnCurEntry = row; + nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = mnCount + 1; + return sal_False; + } + } + else if ( row == 0 ) + { + throw SQLException(); + } + else + { + if ( mnCount + row + 1 > 0 ) + { + mnCurEntry = mnCount + row + 1; + nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return sal_False; + } + } +} + +//------------------------------------------------------------------------- +/** + moves the cursor a relative number of rows, either positive or negative. + <p> + Attempting to move beyond the first/last row in the result set positions + the cursor before/after the first/last row. Calling + <code>moveRelative(0)</code> is valid, but does not change the cursor + position. + <p>Note: Calling <code>moveRelative(1)</code> is different from calling + <code>moveNext()</code> because is makes sense to call + <code>moveNext()</code> when there is no current row, for example, + when the cursor is positioned before the first row or after the last + row of the result set. + @param rows + is the number of rows to move. Could be negative. + @returns + <sal_True/> if the cursor is on a valid row; <sal_False/> if it is off + the result set. + @throws SQLException + if a database access error occurs or if there is no + current row, or the result set type is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::relative( sal_Int32 rows ) + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + if ( rows == 0 ) + return sal_True; + + sal_Int32 nTmp = mnCurEntry + rows; + + if ( nTmp <= 0 ) + { + mnCurEntry = 0; + return sal_False; + } + else if ( nTmp > mnCount ) + { + mnCurEntry = mnCount + 1; + return sal_False; + } + else + { + mnCurEntry = nTmp; + nTmp = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nTmp ); + } +} + +//------------------------------------------------------------------------- +/** + moves the cursor to the previous row in the result set. + <p>Note: <code>previous()</code> is not the same as + <code>relative(-1)</code> because it makes sense to call + <code>previous()</code> when there is no current row. + @returns <sal_True/> if the cursor is on a valid row; <sal_False/> if it is off + the result set. + @throws SQLException + if a database access error occurs or the result set type + is FORWARD_ONLY. + */ +sal_Bool SAL_CALL SortedResultSet::previous() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + mnCurEntry -= 1; + + if ( mnCurEntry > 0 ) + { + if ( mnCurEntry <= mnCount ) + { + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + } + else + mnCurEntry = 0; + + return sal_False; +} + +//------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::refreshRow() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + mxOriginal->refreshRow(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowUpdated() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowUpdated(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowInserted() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowInserted(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::rowDeleted() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowDeleted(); +} + +//------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL SortedResultSet::getStatement() + throw ( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->getStatement(); +} + +//-------------------------------------------------------------------------- +// XRow methods. +//-------------------------------------------------------------------------- + +sal_Bool SAL_CALL SortedResultSet::wasNull() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->wasNull(); +} + +//------------------------------------------------------------------------- +OUString SAL_CALL SortedResultSet::getString( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getString( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL SortedResultSet::getBoolean( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBoolean( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int8 SAL_CALL SortedResultSet::getByte( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getByte( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int16 SAL_CALL SortedResultSet::getShort( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getShort( columnIndex ); +} + +//------------------------------------------------------------------------- +sal_Int32 SAL_CALL SortedResultSet::getInt( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getInt( columnIndex ); +} +//------------------------------------------------------------------------- +sal_Int64 SAL_CALL SortedResultSet::getLong( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getLong( columnIndex ); +} + +//------------------------------------------------------------------------- +float SAL_CALL SortedResultSet::getFloat( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getFloat( columnIndex ); +} + +//------------------------------------------------------------------------- +double SAL_CALL SortedResultSet::getDouble( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDouble( columnIndex ); +} + +//------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL SortedResultSet::getBytes( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBytes( columnIndex ); +} + +//------------------------------------------------------------------------- +Date SAL_CALL SortedResultSet::getDate( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDate( columnIndex ); +} + +//------------------------------------------------------------------------- +Time SAL_CALL SortedResultSet::getTime( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTime( columnIndex ); +} + +//------------------------------------------------------------------------- +DateTime SAL_CALL SortedResultSet::getTimestamp( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTimestamp( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XInputStream > SAL_CALL +SortedResultSet::getBinaryStream( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBinaryStream( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XInputStream > SAL_CALL +SortedResultSet::getCharacterStream( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getCharacterStream( columnIndex ); +} + +//------------------------------------------------------------------------- +Any SAL_CALL SortedResultSet::getObject( sal_Int32 columnIndex, + const Reference< XNameAccess >& typeMap ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getObject( columnIndex, + typeMap); +} + +//------------------------------------------------------------------------- +Reference< XRef > SAL_CALL SortedResultSet::getRef( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getRef( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL SortedResultSet::getBlob( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBlob( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XClob > SAL_CALL SortedResultSet::getClob( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getClob( columnIndex ); +} + +//------------------------------------------------------------------------- +Reference< XArray > SAL_CALL SortedResultSet::getArray( sal_Int32 columnIndex ) + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getArray( columnIndex ); +} + + +//-------------------------------------------------------------------------- +// XCloseable methods. +//-------------------------------------------------------------------------- + +void SAL_CALL SortedResultSet::close() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + Reference< XCloseable >::query(mxOriginal)->close(); +} + +//-------------------------------------------------------------------------- +// XResultSetMetaDataSupplier methods. +//-------------------------------------------------------------------------- + +Reference< XResultSetMetaData > SAL_CALL SortedResultSet::getMetaData() + throw( SQLException, RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XResultSetMetaDataSupplier >::query(mxOriginal)->getMetaData(); +} + + +//-------------------------------------------------------------------------- +// XPropertySet methods. +//-------------------------------------------------------------------------- + +Reference< XPropertySetInfo > SAL_CALL +SortedResultSet::getPropertySetInfo() throw( RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropSetInfo ) + { + mpPropSetInfo = new SRSPropertySetInfo(); + mpPropSetInfo->acquire(); + } + + return Reference< XPropertySetInfo >( mpPropSetInfo ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::setPropertyValue( + const OUString& PropertyName, + const Any& ) + throw( UnknownPropertyException, + PropertyVetoException, + IllegalArgumentException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( PropertyName.compareToAscii( "RowCount" ) == 0 ) || + ( PropertyName.compareToAscii( "IsRowCountFinal" ) == 0 ) ) + throw IllegalArgumentException(); + else + throw UnknownPropertyException(); +} + +//-------------------------------------------------------------------------- +Any SAL_CALL SortedResultSet::getPropertyValue( const OUString& PropertyName ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + Any aRet; + + if ( PropertyName.compareToAscii( "RowCount" ) == 0 ) + { + aRet <<= maS2O.Count(); + } + else if ( PropertyName.compareToAscii( "IsRowCountFinal" ) == 0 ) + { + sal_uInt32 nOrgCount = 0; + sal_Bool bOrgFinal = false; + Any aOrgRet; + + aRet <<= (sal_Bool) sal_False; + + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue( PropertyName ); + aOrgRet >>= bOrgFinal; + + if ( bOrgFinal ) + { + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue( OUString::createFromAscii( "RowCount" ) ); + aOrgRet >>= nOrgCount; + if ( nOrgCount == maS2O.Count() ) + aRet <<= (sal_Bool) sal_True; + } + } + else + throw UnknownPropertyException(); + + return aRet; +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addPropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + mpPropChangeListeners = + new PropertyChangeListeners_Impl(); + + mpPropChangeListeners->addInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removePropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpPropChangeListeners ) + mpPropChangeListeners->removeInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::addVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpVetoChangeListeners ) + mpVetoChangeListeners = + new PropertyChangeListeners_Impl(); + + mpVetoChangeListeners->addInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +void SAL_CALL SortedResultSet::removeVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) + throw( UnknownPropertyException, + WrappedTargetException, + RuntimeException ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpVetoChangeListeners ) + mpVetoChangeListeners->removeInterface( PropertyName, Listener ); +} + +//-------------------------------------------------------------------------- +// private methods +//-------------------------------------------------------------------------- +long SortedResultSet::CompareImpl( Reference < XResultSet > xResultOne, + Reference < XResultSet > xResultTwo, + long nIndexOne, long nIndexTwo, + SortInfo* pSortInfo ) + + throw( SQLException, RuntimeException ) +{ + Reference < XRow > xRowOne = Reference< XRow >::query( xResultOne ); + Reference < XRow > xRowTwo = Reference< XRow >::query( xResultTwo ); + + long nCompare = 0; + long nColumn = pSortInfo->mnColumn; + + switch ( pSortInfo->mnType ) + { + case DataType::BIT : + case DataType::TINYINT : + case DataType::SMALLINT : + case DataType::INTEGER : + { + sal_Int32 aOne = 0; + sal_Int32 aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getInt( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getInt( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::BIGINT : + { + sal_Int64 aOne = 0; + sal_Int64 aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getLong( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getLong( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::CHAR : + case DataType::VARCHAR : + case DataType::LONGVARCHAR : + { + OUString aOne, aTwo; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getString( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getString( nColumn ); + + if ( ! pSortInfo->mbCaseSensitive ) + { + aOne = aOne.toAsciiLowerCase(); + aTwo = aTwo.toAsciiLowerCase(); + } + + nCompare = aOne.compareTo( aTwo ); + break; + } + case DataType::DATE : + { + Date aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getDate( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getDate( nColumn ); + + nTmp = (sal_Int32) aTwo.Year - (sal_Int32) aOne.Year; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Month - (sal_Int32) aOne.Month; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.Day - (sal_Int32) aOne.Day; + } + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::TIME : + { + Time aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getTime( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getTime( nColumn ); + + nTmp = (sal_Int32) aTwo.Hours - (sal_Int32) aOne.Hours; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Minutes - (sal_Int32) aOne.Minutes; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Seconds - (sal_Int32) aOne.Seconds; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.HundredthSeconds + - (sal_Int32) aOne.HundredthSeconds; + }} + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::TIMESTAMP : + { + DateTime aOne, aTwo; + sal_Int32 nTmp; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getTimestamp( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getTimestamp( nColumn ); + + nTmp = (sal_Int32) aTwo.Year - (sal_Int32) aOne.Year; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Month - (sal_Int32) aOne.Month; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Day - (sal_Int32) aOne.Day; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Hours - (sal_Int32) aOne.Hours; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Minutes - (sal_Int32) aOne.Minutes; + if ( !nTmp ) { + nTmp = (sal_Int32) aTwo.Seconds - (sal_Int32) aOne.Seconds; + if ( !nTmp ) + nTmp = (sal_Int32) aTwo.HundredthSeconds + - (sal_Int32) aOne.HundredthSeconds; + }}}}} + + if ( nTmp < 0 ) + nCompare = -1; + else if ( nTmp == 0 ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::REAL : + { + float aOne = 0; + float aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getFloat( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getFloat( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + case DataType::FLOAT : + case DataType::DOUBLE : + { + double aOne = 0; + double aTwo = 0; + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getDouble( nColumn ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getDouble( nColumn ); + + if ( aOne < aTwo ) + nCompare = -1; + else if ( aOne == aTwo ) + nCompare = 0; + else + nCompare = 1; + + break; + } + default: + { + OSL_ENSURE( sal_False, "DataType not supported for compare!" ); + } + } + + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::CompareImpl( Reference < XResultSet > xResultOne, + Reference < XResultSet > xResultTwo, + long nIndexOne, long nIndexTwo ) + throw( SQLException, RuntimeException ) +{ + long nCompare = 0; + SortInfo* pInfo = mpSortInfo; + + while ( !nCompare && pInfo ) + { + if ( pInfo->mbUseOwnCompare ) + { + nCompare = CompareImpl( xResultOne, xResultTwo, + nIndexOne, nIndexTwo, pInfo ); + } + else + { + Any aOne, aTwo; + + Reference < XRow > xRowOne = + Reference< XRow >::query( xResultOne ); + Reference < XRow > xRowTwo = + Reference< XRow >::query( xResultTwo ); + + if ( xResultOne->absolute( nIndexOne ) ) + aOne = xRowOne->getObject( pInfo->mnColumn, NULL ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getObject( pInfo->mnColumn, NULL ); + + nCompare = pInfo->mxCompareFunction->compare( aOne, aTwo ); + } + + if ( ! pInfo->mbAscending ) + nCompare = - nCompare; + + pInfo = pInfo->mpNext; + } + + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::Compare( SortListData *pOne, + SortListData *pTwo ) + throw( SQLException, RuntimeException ) +{ + long nIndexOne; + long nIndexTwo; + + Reference < XResultSet > xResultOne; + Reference < XResultSet > xResultTwo; + + if ( pOne->mbModified ) + { + xResultOne = mxOther; + nIndexOne = pOne->mnOldPos; + } + else + { + xResultOne = mxOriginal; + nIndexOne = pOne->mnCurPos; + } + + if ( pTwo->mbModified ) + { + xResultTwo = mxOther; + nIndexTwo = pTwo->mnOldPos; + } + else + { + xResultTwo = mxOriginal; + nIndexTwo = pTwo->mnCurPos; + } + + long nCompare; + nCompare = CompareImpl( xResultOne, xResultTwo, + nIndexOne, nIndexTwo ); + return nCompare; +} + +//-------------------------------------------------------------------------- +long SortedResultSet::FindPos( SortListData *pEntry, + long _nStart, long _nEnd ) + throw( SQLException, RuntimeException ) +{ + if ( _nStart > _nEnd ) + return _nStart + 1; + + long nStart = _nStart; + long nEnd = _nEnd; + long nMid = 0, nCompare = 0; + + SortListData *pMid; + + while ( nStart <= nEnd ) + { + nMid = ( nEnd - nStart ) / 2 + nStart; + pMid = maS2O.GetData( nMid ); + nCompare = Compare( pEntry, pMid ); + + if ( !nCompare ) + nCompare = ((long) pEntry ) - ( (long) pMid ); + + if ( nCompare < 0 ) // pEntry < pMid + nEnd = nMid - 1; + else + nStart = nMid + 1; + } + + if ( nCompare < 0 ) // pEntry < pMid + return nMid; + else + return nMid+1; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::PropertyChanged( const PropertyChangeEvent& rEvt ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + return; + + // Notify listeners interested especially in the changed property. + OInterfaceContainerHelper* pPropsContainer = + mpPropChangeListeners->getContainer( rEvt.PropertyName ); + if ( pPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } + + // Notify listeners interested in all properties. + pPropsContainer = mpPropChangeListeners->getContainer( OUString() ); + if ( pPropsContainer ) + { + OInterfaceIteratorHelper aIter( *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + Reference< XPropertyChangeListener > xListener( + aIter.next(), UNO_QUERY ); + if ( xListener.is() ) + xListener->propertyChange( rEvt ); + } + } +} + +//------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// public methods +//-------------------------------------------------------------------------- + +void SortedResultSet::CopyData( SortedResultSet *pSource ) +{ + const SortedEntryList *pSrcS2O = pSource->GetS2OList(); + const SimpleList *pSrcO2S = pSource->GetO2SList(); + + long i, nCount; + + maS2O.Clear(); + maO2S.Clear(); + maModList.Clear(); + + maS2O.Insert( NULL, 0 ); + maO2S.Insert( 0, (sal_uInt32) 0 ); // value, pos + + nCount = pSrcS2O->Count(); + + for ( i=1; i<nCount; i++ ) + { + maS2O.Insert( new SortListData( (*pSrcS2O)[ i ] ), i ); + maO2S.Insert( pSrcO2S->GetObject( i ), (sal_uInt32) i ); + } + + mnLastSort = maS2O.Count(); + mxOther = pSource->GetResultSet(); + + if ( !mpSortInfo ) + { + mpSortInfo = pSource->GetSortInfo(); + mbIsCopy = sal_True; + } +} + +//-------------------------------------------------------------------------- +void SortedResultSet::Initialize( + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + BuildSortInfo( mxOriginal, xSortInfo, xCompFactory ); + // Insert dummy at pos 0 + SortListData *pData = new SortListData( 0 ); + maS2O.Insert( pData, 0 ); + + long nIndex = 1; + + // now fetch all the elements from the original result set, + // get there new position in the sorted result set and insert + // an entry in the sorted to original mapping list + try { + while ( mxOriginal->absolute( nIndex ) ) + { + pData = new SortListData( nIndex ); + long nPos = FindPos( pData, 1, nIndex-1 ); + + maS2O.Insert( pData, nPos ); + + nIndex++; + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::Initialize() : Got unexpected SQLException" ); } + + // when we have fetched all the elements, we can create the + // original to sorted mapping list from the s2o list + maO2S.Clear(); + maO2S.Insert( NULL, (sal_uInt32) 0 ); + + // insert some dummy entries first and replace then + // the entries with the right ones + sal_uInt32 i; + + for ( i=1; i<maS2O.Count(); i++ ) + maO2S.Insert( (void*) 0, i ); // Insert( data, pos ) + for ( i=1; i<maS2O.Count(); i++ ) + maO2S.Replace( (void*) i, maS2O[ i ] ); // Insert( data, pos ) + + mnCount = maS2O.Count() - 1; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::CheckProperties( long nOldCount, sal_Bool bWasFinal ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + return; + + try { + // check for propertyChangeEvents + if ( nOldCount != GetCount() ) + { + sal_Bool bIsFinal = sal_False; + PropertyChangeEvent aEvt; + + aEvt.PropertyName = OUString::createFromAscii( "RowCount" ); + aEvt.Further = sal_False; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= nOldCount; + aEvt.NewValue <<= GetCount(); + + PropertyChanged( aEvt ); + + OUString aName = OUString::createFromAscii( "IsRowCountFinal" ); + Any aRet = getPropertyValue( aName ); + if ( (aRet >>= bIsFinal) && bIsFinal != bWasFinal ) + { + aEvt.PropertyName = aName; + aEvt.Further = sal_False; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= (sal_Bool) bWasFinal; + aEvt.NewValue <<= (sal_Bool) bIsFinal; + PropertyChanged( aEvt ); + } + } + } + catch ( UnknownPropertyException ) {} + catch ( WrappedTargetException ) {} +} + +//------------------------------------------------------------------------- +void SortedResultSet::InsertNew( long nPos, long nCount ) +{ + // in der maS2O Liste alle Einträge, die >= nPos sind, um nCount + // erhöhen + SortListData *pData; + long i, nEnd; + + nEnd = maS2O.Count(); + for ( i=1; i<=nEnd; i++ ) + { + pData = maS2O.GetData( i ); + if ( pData->mnCurPos >= nPos ) + { + pData->mnCurPos += nCount; + } + } + + // und die neuen einträge hinten an die maS2O Liste anhängen bzw + // an der Position nPos in der maO2S Liste einfügen + for ( i=0; i<nCount; i++ ) + { + nEnd += 1; + pData = new SortListData( nEnd ); + + maS2O.Insert( pData, nEnd ); // Insert( Wert, Position ) + maO2S.Insert( (void*)nEnd, (sal_uInt32)(nPos+i) ); // Insert( Wert, Position ) + } + + mnCount += nCount; +} + +//------------------------------------------------------------------------- +void SortedResultSet::Remove( long nPos, long nCount, EventList *pEvents ) +{ + sal_uInt32 i, j; + long nOldLastSort; + + // correct mnLastSort first + nOldLastSort = mnLastSort; + if ( nPos <= mnLastSort ) + { + if ( nPos + nCount - 1 <= mnLastSort ) + mnLastSort -= nCount; + else + mnLastSort = nPos - 1; + } + + // remove the entries from the lists and correct the positions + // in the original2sorted list + for ( i=0; i < (sal_uInt32) nCount; i++ ) + { + long nSortPos = (long) maO2S.GetObject( nPos ); + maO2S.Remove( (sal_uInt32) nPos ); + + for ( j=1; j<=maO2S.Count(); j++ ) + { + long nVal = (long) maO2S.GetObject( j ); + if ( nVal > nSortPos ) + { + --nVal; + maO2S.Replace( (void*) nVal, j ); + } + } + + SortListData *pData = maS2O.Remove( nSortPos ); + if ( pData->mbModified ) + maModList.Remove( (void*) pData ); + delete pData; + + // generate remove Event, but not for new entries + if ( nSortPos <= nOldLastSort ) + pEvents->AddEvent( ListActionType::REMOVED, nSortPos, 1 ); + } + + // correct the positions in the sorted list + for ( i=1; i<= maS2O.Count(); i++ ) + { + SortListData *pData = maS2O.GetData( i ); + if ( pData->mnCurPos > nPos ) + pData->mnCurPos -= nCount; + } + + mnCount -= nCount; +} + +//------------------------------------------------------------------------- +void SortedResultSet::Move( long nPos, long nCount, long nOffset ) +{ + if ( !nOffset ) + return; + + long i, nSortPos, nTo; + SortListData *pData; + + for ( i=0; i<nCount; i++ ) + { + nSortPos = (long) maO2S.GetObject( nPos+i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nOffset; + } + + if ( nOffset < 0 ) + { + for ( i=nPos+nOffset; i<nPos; i++ ) + { + nSortPos = (long) maO2S.GetObject( i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nCount; + } + } + else + { + long nStart = nPos + nCount; + long nEnd = nStart + nOffset; + for ( i=nStart; i<nEnd; i++ ) + { + nSortPos = (long) maO2S.GetObject( i ); + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos -= nCount; + } + } + + // remember the to be moved entries + long *pTmpArr = new long[ nCount ]; + for ( i=0; i<nCount; i++ ) + pTmpArr[i] = (long)maO2S.GetObject( (sal_uInt32)( nPos+i ) ); + + // now move the entries, which are in the way + if ( nOffset < 0 ) + { + // be carefully here, because nOffset is negative here, so an + // addition is a subtraction + long nFrom = nPos - 1; + nTo = nPos + nCount - 1; + + // same for i here + for ( i=0; i>nOffset; i-- ) + { + long nVal = (long) maO2S.GetObject( (sal_uInt32)( nFrom+i ) ); + maO2S.Replace( (void*) nVal, (sal_uInt32)( nTo+i ) ); + } + + } + else + { + long nStart = nPos + nCount; + for ( i=0; i<nOffset; i++ ) + { + long nVal = (long) maO2S.GetObject( (sal_uInt32)( nStart+i ) ); + maO2S.Replace( (void*) nVal, (sal_uInt32)( nPos+i ) ); + } + } + + // finally put the remembered entries at there new location + nTo = nPos + nOffset; + for ( i=0; i<nCount; i++ ) + { + maO2S.Replace( (void*)pTmpArr[ i ], (sal_uInt32)( nTo+i ) ); + } + + delete [] pTmpArr; +} + +//-------------------------------------------------------------------------- +void SortedResultSet::BuildSortInfo( + Reference< XResultSet > aResult, + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + Reference < XResultSetMetaDataSupplier > xMeta ( aResult, UNO_QUERY ); + + if ( ! xMeta.is() ) + { + OSL_ENSURE( sal_False, "No MetaData, No Sorting!" ); + return; + } + + Reference < XResultSetMetaData > xData = xMeta->getMetaData(); + const NumberedSortingInfo *pSortInfo = xSortInfo.getConstArray(); + + sal_Int32 nColumn; + OUString aPropName; + SortInfo *pInfo; + + for ( long i=xSortInfo.getLength(); i > 0; ) + { + --i; + nColumn = pSortInfo[ i ].ColumnIndex; + aPropName = xData->getColumnName( nColumn ); + pInfo = new SortInfo; + + if ( xCompFactory.is() ) + pInfo->mxCompareFunction = xCompFactory->createAnyCompareByName( + aPropName ); + + if ( pInfo->mxCompareFunction.is() ) + { + pInfo->mbUseOwnCompare = sal_False; + pInfo->mnType = 0; + } + else + { + pInfo->mbUseOwnCompare = sal_True; + pInfo->mnType = xData->getColumnType( nColumn ); + } + + pInfo->mnColumn = nColumn; + pInfo->mbAscending = pSortInfo[ i ].Ascending; + pInfo->mbCaseSensitive = xData->isCaseSensitive( nColumn ); + pInfo->mpNext = mpSortInfo; + mpSortInfo = pInfo; + } +} + +//------------------------------------------------------------------------- +void SortedResultSet::SetChanged( long nPos, long nCount ) +{ + for ( long i=0; i<nCount; i++ ) + { + long nSortPos = (long) maO2S.GetObject( nPos ); + if ( nSortPos < mnLastSort ) + { + SortListData *pData = maS2O.GetData( nSortPos ); + if ( ! pData->mbModified ) + { + pData->mbModified = sal_True; + maModList.Append( pData ); + } + } + nPos += 1; + } +} + +//------------------------------------------------------------------------- +void SortedResultSet::ResortModified( EventList* pList ) +{ + sal_uInt32 i, j; + long nCompare, nCurPos, nNewPos; + long nStart, nEnd, nOffset, nVal; + SortListData *pData; + ListAction *pAction; + + try { + for ( i=0; i<maModList.Count(); i++ ) + { + pData = (SortListData*) maModList.GetObject( i ); + nCompare = CompareImpl( mxOther, mxOriginal, + pData->mnOldPos, pData->mnCurPos ); + pData->mbModified = sal_False; + if ( nCompare != 0 ) + { + nCurPos = (long) maO2S.GetObject( (sal_uInt32) pData->mnCurPos ); + if ( nCompare < 0 ) + { + nNewPos = FindPos( pData, 1, nCurPos-1 ); + nStart = nNewPos; + nEnd = nCurPos; + nOffset = 1; + } + else + { + nNewPos = FindPos( pData, nCurPos+1, mnLastSort ); + nStart = nCurPos; + nEnd = mnLastSort; + nOffset = -1; + } + + if ( nNewPos != nCurPos ) + { + // correct the lists! + maS2O.Remove( (sal_uInt32) nCurPos ); + maS2O.Insert( pData, nNewPos ); + for ( j=1; j<maO2S.Count(); j++ ) + { + nVal = (long) maO2S.GetObject( (sal_uInt32)( j ) ); + if ( ( nStart <= nVal ) && ( nVal <= nEnd ) ) + { + nVal += nOffset; + maO2S.Replace( (void*) (nVal), (sal_uInt32)( j ) ); + } + } + + maO2S.Replace( (void*) nNewPos, (sal_uInt32) pData->mnCurPos ); + + pAction = new ListAction; + pAction->Position = nCurPos; + pAction->Count = 1; + pAction->ListActionType = ListActionType::MOVED; + pAction->ActionInfo <<= nNewPos-nCurPos; + pList->Insert( pAction ); + } + pList->AddEvent( ListActionType::PROPERTIES_CHANGED, + nNewPos, 1 ); + } + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::ResortModified() : Got unexpected SQLException" ); } + + maModList.Clear(); +} + +//------------------------------------------------------------------------- +void SortedResultSet::ResortNew( EventList* pList ) +{ + long i, j, nNewPos, nVal; + SortListData *pData; + + try { + for ( i = mnLastSort; i<(long)maS2O.Count(); i++ ) + { + pData = (SortListData*) maModList.GetObject( i ); + nNewPos = FindPos( pData, 1, mnLastSort ); + if ( nNewPos != i ) + { + maS2O.Remove( (sal_uInt32) i ); + maS2O.Insert( pData, nNewPos ); + // maO2S liste korigieren + for ( j=1; j<(long)maO2S.Count(); j++ ) + { + nVal = (long) maO2S.GetObject( (sal_uInt32)( j ) ); + if ( nVal >= nNewPos ) + maO2S.Replace( (void*) (nVal+1), (sal_uInt32)( j ) ); + } + maO2S.Replace( (void*) nNewPos, (sal_uInt32) pData->mnCurPos ); + } + mnLastSort++; + pList->AddEvent( ListActionType::INSERTED, nNewPos, 1 ); + } + } + catch ( SQLException ) { OSL_ENSURE( sal_False, "SortedResultSet::ResortNew() : Got unexpected SQLException" ); } +} + +//------------------------------------------------------------------------- +// +// SortListData +// +//------------------------------------------------------------------------- +SortListData::SortListData( long nPos, sal_Bool bModified ) +{ + mbModified = bModified; + mnCurPos = nPos; + mnOldPos = nPos; +}; + + +//========================================================================= +void SortedEntryList::Clear() +{ + for ( std::deque< LISTACTION* >::size_type i = 0; + i < maData.size(); ++i ) + { + delete maData[i]; + } + + maData.clear(); +} + +//------------------------------------------------------------------------- +void SortedEntryList::Insert( SortListData *pEntry, long nPos ) +{ + if ( nPos < (long) maData.size() ) + maData.insert( maData.begin() + nPos, pEntry ); + else + maData.push_back( pEntry ); +} + +//------------------------------------------------------------------------- +SortListData* SortedEntryList::Remove( long nPos ) +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + { + pData = maData[ nPos ]; + maData.erase( maData.begin() + nPos ); + } + else + pData = NULL; + + return pData; +} + +//------------------------------------------------------------------------- +SortListData* SortedEntryList::GetData( long nPos ) +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + pData = maData[ nPos ]; + else + pData = NULL; + + return pData; +} + +//------------------------------------------------------------------------- +long SortedEntryList::operator [] ( long nPos ) const +{ + SortListData *pData; + + if ( nPos < (long) maData.size() ) + pData = maData[ nPos ]; + else + pData = NULL; + + if ( pData ) + if ( ! pData->mbModified ) + return pData->mnCurPos; + else + { + OSL_ENSURE( sal_False, "SortedEntryList: Can't get value for modified entry!"); + return 0; + } + else + { + OSL_ENSURE( sal_False, "SortedEntryList: invalid pos!"); + return 0; + } +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +void SimpleList::Remove( sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + { + maData.erase( maData.begin() + nPos ); + } +} + +//------------------------------------------------------------------------- +void SimpleList::Remove( void* pData ) +{ + sal_Bool bFound = sal_False; + sal_uInt32 i; + + for ( i = 0; i < (sal_uInt32) maData.size(); i++ ) + { + if ( maData[ i ] == pData ) + { + bFound = sal_True; + break; + } + } + + if ( bFound ) + maData.erase( maData.begin() + i ); +} + +//------------------------------------------------------------------------- +void SimpleList::Insert( void* pData, sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + maData.insert( maData.begin() + nPos, pData ); + else + maData.push_back( pData ); +} + +//------------------------------------------------------------------------- +void* SimpleList::GetObject( sal_uInt32 nPos ) const +{ + if ( nPos < (sal_uInt32) maData.size() ) + return maData[ nPos ]; + else + return NULL; +} + +//------------------------------------------------------------------------- +void SimpleList::Replace( void* pData, sal_uInt32 nPos ) +{ + if ( nPos < (sal_uInt32) maData.size() ) + maData[ nPos ] = pData; +} + +//------------------------------------------------------------------------- +// +// class SRSPropertySetInfo. +// +//------------------------------------------------------------------------- + +SRSPropertySetInfo::SRSPropertySetInfo() +{ + maProps[0].Name = OUString::createFromAscii( "RowCount" ); + maProps[0].Handle = -1; + maProps[0].Type = ::getCppuType( (const OUString*) NULL ); + maProps[0].Attributes = -1; + + maProps[1].Name = OUString::createFromAscii( "IsRowCountFinal" ); + maProps[1].Handle = -1; + maProps[1].Type = ::getBooleanCppuType(); + maProps[1].Attributes = -1; +} + +//------------------------------------------------------------------------- +SRSPropertySetInfo::~SRSPropertySetInfo() +{} + +//------------------------------------------------------------------------- +// XInterface methods. +//------------------------------------------------------------------------- + +XINTERFACE_IMPL_2( SRSPropertySetInfo, + XTypeProvider, + XPropertySetInfo ); + +//------------------------------------------------------------------------- +// XTypeProvider methods. +//------------------------------------------------------------------------- + +XTYPEPROVIDER_IMPL_2( SRSPropertySetInfo, + XTypeProvider, + XPropertySetInfo ); + +//------------------------------------------------------------------------- +// XPropertySetInfo methods. +//------------------------------------------------------------------------- +Sequence< Property > SAL_CALL +SRSPropertySetInfo::getProperties() throw( RuntimeException ) +{ + return Sequence < Property > ( maProps, 2 ); +} + +//------------------------------------------------------------------------- +Property SAL_CALL +SRSPropertySetInfo::getPropertyByName( const OUString& Name ) + throw( UnknownPropertyException, RuntimeException ) +{ + if ( Name.compareToAscii( "RowCount" ) == 0 ) + return maProps[0]; + else if ( Name.compareToAscii( "IsRowCountFinal" ) == 0 ) + return maProps[1]; + else + throw UnknownPropertyException(); +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL +SRSPropertySetInfo::hasPropertyByName( const OUString& Name ) + throw( RuntimeException ) +{ + if ( Name.compareToAscii( "RowCount" ) == 0 ) + return sal_True; + else if ( Name.compareToAscii( "IsRowCountFinal" ) == 0 ) + return sal_True; + else + return sal_False; +} + diff --git a/ucb/source/sorter/sortresult.hxx b/ucb/source/sorter/sortresult.hxx new file mode 100644 index 000000000000..3817152f3d6c --- /dev/null +++ b/ucb/source/sorter/sortresult.hxx @@ -0,0 +1,455 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SORTRESULT_HXX +#define _SORTRESULT_HXX + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/ucb/NumberedSortingInfo.hpp> +#include <com/sun/star/ucb/XAnyCompareFactory.hpp> +#include <com/sun/star/ucb/ListAction.hpp> +#include <cppuhelper/weak.hxx> +#include <osl/mutex.hxx> + +#include <deque> +#include <ucbhelper/macros.hxx> + +namespace cppu { + class OInterfaceContainerHelper; +} + +//----------------------------------------------------------------------------- +struct SortInfo; +struct SortListData; +class SRSPropertySetInfo; +class PropertyChangeListeners_Impl; + +//----------------------------------------------------------------------------- +class SortedEntryList +{ + std::deque < SortListData* > maData; + +public: + SortedEntryList(){} + ~SortedEntryList(){ Clear(); } + + sal_uInt32 Count() const { return (sal_uInt32) maData.size(); } + + void Clear(); + void Insert( SortListData *pEntry, long nPos ); + SortListData* Remove( long nPos ); + SortListData* GetData( long nPos ); + + long operator [] ( long nPos ) const; +}; + +//----------------------------------------------------------------------------- +#define LISTACTION com::sun::star::ucb::ListAction + +class EventList +{ + std::deque < LISTACTION* > maData; + +public: + EventList(){} + ~EventList(){ Clear(); } + + sal_uInt32 Count() { return (sal_uInt32) maData.size(); } + + void AddEvent( long nType, long nPos, long nCount ); + void Insert( LISTACTION *pAction ) { maData.push_back( pAction ); } + void Clear(); + LISTACTION* GetAction( long nIndex ) { return maData[ nIndex ]; } +}; + +//----------------------------------------------------------------------------- + +class SimpleList +{ + std::deque < void* > maData; + +public: + SimpleList(){} + ~SimpleList(){ Clear(); } + + sal_uInt32 Count() { return (sal_uInt32) maData.size(); } + void Clear() { maData.clear(); } + + void Remove( sal_uInt32 nPos ); + void Remove( void* pData ); + + void Append( void* pData ) + { maData.push_back( pData ); } + void Insert( void* pData, sal_uInt32 nPos ); + void* GetObject( sal_uInt32 nPos ) const; + void Replace( void* pData, sal_uInt32 nPos ); +}; + +//----------------------------------------------------------------------------- + +#define PROPERTYCHANGEEVENT com::sun::star::beans::PropertyChangeEvent +#define RUNTIME_EXCEPTION com::sun::star::uno::RuntimeException +#define REFERENCE com::sun::star::uno::Reference +#define SEQUENCE com::sun::star::uno::Sequence +#define XEVENTLISTENER com::sun::star::lang::XEventListener +#define XRESULTSET com::sun::star::sdbc::XResultSet +#define SQLEXCEPTION com::sun::star::sdbc::SQLException +#define XRESULTSETMETADATA com::sun::star::sdbc::XResultSetMetaData +#define NUMBERED_SORTINGINFO com::sun::star::ucb::NumberedSortingInfo +#define XANYCOMPAREFACTORY com::sun::star::ucb::XAnyCompareFactory + +#define RESULTSET_SERVICE_NAME "com.sun.star.ucb.SortedResultSet" + +//----------------------------------------------------------------------------- + +class SortedResultSet: + public cppu::OWeakObject, + public com::sun::star::lang::XTypeProvider, + public com::sun::star::lang::XServiceInfo, + public com::sun::star::lang::XComponent, + public com::sun::star::ucb::XContentAccess, + public XRESULTSET, + public com::sun::star::sdbc::XRow, + public com::sun::star::sdbc::XCloseable, + public com::sun::star::sdbc::XResultSetMetaDataSupplier, + public com::sun::star::beans::XPropertySet +{ + cppu::OInterfaceContainerHelper *mpDisposeEventListeners; + PropertyChangeListeners_Impl *mpPropChangeListeners; + PropertyChangeListeners_Impl *mpVetoChangeListeners; + + REFERENCE < XRESULTSET > mxOriginal; + REFERENCE < XRESULTSET > mxOther; + + SRSPropertySetInfo* mpPropSetInfo; + SortInfo* mpSortInfo; + osl::Mutex maMutex; + SortedEntryList maS2O; // maps the sorted entries to the original ones + SimpleList maO2S; // maps the original Entries to the sorted ones + SimpleList maModList; // keeps track of modified entries + long mnLastSort; // index of the last sorted entry; + long mnCurEntry; // index of the current entry + long mnCount; // total count of the elements + sal_Bool mbIsCopy; + + +private: + + long FindPos( SortListData *pEntry, long nStart, long nEnd ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + long Compare( SortListData *pOne, + SortListData *pTwo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + void BuildSortInfo( REFERENCE< XRESULTSET > aResult, + const SEQUENCE < NUMBERED_SORTINGINFO > &xSortInfo, + const REFERENCE< XANYCOMPAREFACTORY > &xCompFac ); + long CompareImpl( REFERENCE < XRESULTSET > xResultOne, + REFERENCE < XRESULTSET > xResultTwo, + long nIndexOne, long nIndexTwo, + SortInfo* pSortInfo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + long CompareImpl( REFERENCE < XRESULTSET > xResultOne, + REFERENCE < XRESULTSET > xResultTwo, + long nIndexOne, long nIndexTwo ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + void PropertyChanged( const PROPERTYCHANGEEVENT& rEvt ); + +public: + SortedResultSet( REFERENCE< XRESULTSET > aResult ); + ~SortedResultSet(); + + const SortedEntryList* GetS2OList() const { return &maS2O; } + const SimpleList* GetO2SList() const { return &maO2S; } + REFERENCE < XRESULTSET > GetResultSet() const { return mxOriginal; } + SortInfo* GetSortInfo() const { return mpSortInfo; } + long GetCount() const { return mnCount; } + + void CopyData( SortedResultSet* pSource ); + void Initialize( const SEQUENCE < NUMBERED_SORTINGINFO > &xSortInfo, + const REFERENCE< XANYCOMPAREFACTORY > &xCompFac ); + void CheckProperties( long nOldCount, sal_Bool bWasFinal ); + + void InsertNew( long nPos, long nCount ); + void SetChanged( long nPos, long nCount ); + void Remove( long nPos, long nCount, EventList *pList ); + void Move( long nPos, long nCount, long nOffset ); + + void ResortModified( EventList* pList ); + void ResortNew( EventList* pList ); + + // XInterface + XINTERFACE_DECL() + + // XTypeProvider + XTYPEPROVIDER_DECL() + + // XServiceInfo + XSERVICEINFO_NOFACTORY_DECL() + + // XComponent + virtual void SAL_CALL + dispose() throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeEventListener( const REFERENCE< XEVENTLISTENER >& Listener ) + throw( RUNTIME_EXCEPTION ); + + // XContentAccess + virtual rtl::OUString SAL_CALL + queryContentIdentifierString() + throw( RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier() + throw( RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::ucb::XContent > SAL_CALL + queryContent() + throw( RUNTIME_EXCEPTION ); + + // XResultSet + virtual sal_Bool SAL_CALL + next() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isBeforeFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isAfterLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + isLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + beforeFirst() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + afterLast() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + first() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + last() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Int32 SAL_CALL + getRow() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + absolute( sal_Int32 row ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + relative( sal_Int32 rows ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + previous() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual void SAL_CALL + refreshRow() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowUpdated() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowInserted() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual sal_Bool SAL_CALL + rowDeleted() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::uno::XInterface > SAL_CALL + getStatement() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XRow + virtual sal_Bool SAL_CALL + wasNull() throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual rtl::OUString SAL_CALL + getString( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Bool SAL_CALL + getBoolean( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int8 SAL_CALL + getByte( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int16 SAL_CALL + getShort( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int32 SAL_CALL + getInt( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual sal_Int64 SAL_CALL + getLong( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual float SAL_CALL + getFloat( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual double SAL_CALL + getDouble( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::Date SAL_CALL + getDate( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::Time SAL_CALL + getTime( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::util::DateTime SAL_CALL + getTimestamp( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual REFERENCE< + com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual REFERENCE< + com::sun::star::io::XInputStream > SAL_CALL + getCharacterStream( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Any SAL_CALL + getObject( sal_Int32 columnIndex, + const REFERENCE< + com::sun::star::container::XNameAccess >& typeMap ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XRef > SAL_CALL + getRef( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XBlob > SAL_CALL + getBlob( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XClob > SAL_CALL + getClob( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + virtual REFERENCE< + com::sun::star::sdbc::XArray > SAL_CALL + getArray( sal_Int32 columnIndex ) + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XCloseable + virtual void SAL_CALL + close() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + // XResultSetMetaDataSupplier + virtual REFERENCE< XRESULTSETMETADATA > SAL_CALL + getMetaData() + throw( SQLEXCEPTION, RUNTIME_EXCEPTION ); + + + // XPropertySet + virtual REFERENCE< + com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw( RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + setPropertyValue( const rtl::OUString& PropertyName, + const com::sun::star::uno::Any& Value ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual com::sun::star::uno::Any SAL_CALL + getPropertyValue( const rtl::OUString& PropertyName ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addPropertyChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XPropertyChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removePropertyChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XPropertyChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + addVetoableChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XVetoableChangeListener >& Listener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); + + virtual void SAL_CALL + removeVetoableChangeListener( const rtl::OUString& PropertyName, + const REFERENCE< + com::sun::star::beans::XVetoableChangeListener >& aListener ) + throw( com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + RUNTIME_EXCEPTION ); +}; + +#endif + diff --git a/ucb/source/sorter/srtrs.xml b/ucb/source/sorter/srtrs.xml new file mode 100644 index 000000000000..51626a1e6acc --- /dev/null +++ b/ucb/source/sorter/srtrs.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + + <module-name> + srtrs + </module-name> + + <component-description> + <author> + Dirk Voelzke + </author> + <name> + com.sun.star.comp.ucb.SortedDynamicResultSetFactory + </name> + <description> + This component implements a factory for sorted Content Resultsets. + It can be used to sort resultsets obtained from UCB folder contents. + </description> + <loader-name> + com.sun.star.loader.SharedLibrary + </loader-name> + <language> + c++ + </language> + <status value="final"/> + <supported-service> + com.sun.star.ucb.SortedDynamicResultSetFactory + </supported-service> + + <service-dependency> + com.sun.star.ucb.CachedDynamicResultSetStubFactory + </service-dependency> + </component-description> + + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> cppuhelper </project-build-dependency> + + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.sdbc.DataType </type> + <type> com.sun.star.sdbc.XCloseable </type> + <type> com.sun.star.sdbc.XResultSet </type> + <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type> + <type> com.sun.star.sdbc.XRow </type> + <type> com.sun.star.ucb.ContentResultSetCapability </type> + <type> com.sun.star.ucb.ListActionType </type> + <type> com.sun.star.ucb.NumberedSortingInfo </type> + <type> com.sun.star.ucb.WelcomeDynamicResultSetStruct </type> + <type> com.sun.star.ucb.XCachedDynamicResultSetStubFactory </type> + <type> com.sun.star.ucb.XContentAccess </type> + <type> com.sun.star.ucb.XDynamicResultSet </type> + <type> com.sun.star.ucb.XSortedDynamicResultSetFactory </type> + <type> com.sun.star.ucb.XSourceInitialization </type> + <type> com.sun.star.uno.XWeak </type> +</module-description> diff --git a/ucb/source/sorter/srtrs1.component b/ucb/source/sorter/srtrs1.component new file mode 100644 index 000000000000..c32705160c0f --- /dev/null +++ b/ucb/source/sorter/srtrs1.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org 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 Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.SortedDynamicResultSetFactory"> + <service name="com.sun.star.ucb.SortedDynamicResultSetFactory"/> + </implementation> +</component> |