diff options
Diffstat (limited to 'ucb/source/sorter')
-rw-r--r-- | ucb/source/sorter/sortdynres.cxx | 516 | ||||
-rw-r--r-- | ucb/source/sorter/sortdynres.hxx | 164 | ||||
-rw-r--r-- | ucb/source/sorter/sortresult.cxx | 1778 | ||||
-rw-r--r-- | ucb/source/sorter/sortresult.hxx | 329 | ||||
-rw-r--r-- | ucb/source/sorter/srtrs1.component | 26 |
5 files changed, 2813 insertions, 0 deletions
diff --git a/ucb/source/sorter/sortdynres.cxx b/ucb/source/sorter/sortdynres.cxx new file mode 100644 index 000000000..2f7039b55 --- /dev/null +++ b/ucb/source/sorter/sortdynres.cxx @@ -0,0 +1,516 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "sortdynres.hxx" +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/ucb/ContentResultSetCapability.hpp> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/ListenerAlreadySetException.hpp> +#include <com/sun/star/ucb/ServiceNotFoundException.hpp> +#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp> +#include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.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 comphelper; + + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex ourMutex; + + return ourMutex; +} + + +// SortedDynamicResultSet + +SortedDynamicResultSet::SortedDynamicResultSet( + const Reference < XDynamicResultSet > &xOriginal, + const Sequence < NumberedSortingInfo > &aOptions, + const Reference < XAnyCompareFactory > &xCompFac, + const Reference < XComponentContext > &rxContext ) +{ + mpDisposeEventListeners = nullptr; + mxOwnListener = new SortedDynamicResultSetListener( this ); + + mxOriginal = xOriginal; + maOptions = aOptions; + mxCompFac = xCompFac; + m_xContext = rxContext; + + mbGotWelcome = false; + mbUseOne = true; + mbStatic = false; +} + + +SortedDynamicResultSet::~SortedDynamicResultSet() +{ + mxOwnListener->impl_OwnerDies(); + mxOwnListener.clear(); + + mpDisposeEventListeners.reset(); + + mxOne.clear(); + mxTwo.clear(); + mxOriginal.clear(); +} + +// XServiceInfo methods. + +OUString SAL_CALL SortedDynamicResultSet::getImplementationName() +{ + return "com.sun.star.comp.ucb.SortedDynamicResultSet"; +} + +sal_Bool SAL_CALL SortedDynamicResultSet::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSet::getSupportedServiceNames() +{ + return { "com.sun.star.ucb.SortedDynamicResultSet" }; +} + +// XComponent methods. + +void SAL_CALL SortedDynamicResultSet::dispose() +{ + 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(); + + mbUseOne = true; +} + +void SAL_CALL SortedDynamicResultSet::addEventListener( + const Reference< XEventListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners.reset( + new OInterfaceContainerHelper3<XEventListener>( getContainerMutex() ) ); + + mpDisposeEventListeners->addInterface( Listener ); +} + +void SAL_CALL SortedDynamicResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + + +// XDynamicResultSet methods. + +Reference< XResultSet > SAL_CALL +SortedDynamicResultSet::getStaticResultSet() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + mbStatic = true; + + if ( mxOriginal.is() ) + { + mxOne = new SortedResultSet( mxOriginal->getStaticResultSet() ); + mxOne->Initialize( maOptions, mxCompFac ); + } + + return mxOne; +} + + +void SAL_CALL +SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mxListener.is() ) + throw ListenerAlreadySetException(); + + addEventListener( Listener ); + + mxListener = Listener; + + if ( mxOriginal.is() ) + mxOriginal->setListener( mxOwnListener ); +} + + +void SAL_CALL +SortedDynamicResultSet::connectToCache( const Reference< XDynamicResultSet > & xCache ) +{ + if( mxListener.is() ) + throw ListenerAlreadySetException(); + + if( mbStatic ) + throw ListenerAlreadySetException(); + + Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); + if( xTarget.is() && m_xContext.is() ) + { + Reference< XCachedDynamicResultSetStubFactory > xStubFactory; + try + { + xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext ); + } + catch ( Exception const & ) + { + } + + if( xStubFactory.is() ) + { + xStubFactory->connectToCache( + this, xCache, Sequence< NumberedSortingInfo > (), nullptr ); + return; + } + } + throw ServiceNotFoundException(); +} + + +sal_Int16 SAL_CALL SortedDynamicResultSet::getCapabilities() +{ + 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 himself as listener (otherwise you deadlock)!!! +*/ +void SortedDynamicResultSet::impl_notify( const ListEvent& Changes ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + bool bHasNew = false; + bool bHasModified = false; + + SortedResultSet *pCurSet = nullptr; + + // exchange mxNew and mxOld and immediately afterwards copy the tables + // from Old to New + if ( mbGotWelcome ) + { + if ( mbUseOne ) + { + mbUseOne = false; + mxTwo->CopyData( mxOne.get() ); + pCurSet = mxTwo.get(); + } + else + { + mbUseOne = true; + mxOne->CopyData( mxTwo.get() ); + pCurSet = mxOne.get(); + } + } + + if (!pCurSet) + return; + + Any aRet; + + try { + aRet = pCurSet->getPropertyValue("IsRowCountFinal"); + } + catch (const UnknownPropertyException&) {} + catch (const WrappedTargetException&) {} + + sal_Int32 nOldCount = pCurSet->GetCount(); + bool bWasFinal = false; + + aRet >>= bWasFinal; + + // handle the actions in the list + for ( const ListAction& aAction : Changes.Changes ) + { + switch ( aAction.ListActionType ) + { + case ListActionType::WELCOME: + { + WelcomeDynamicResultSetStruct aWelcome; + if ( aAction.ActionInfo >>= aWelcome ) + { + mxTwo = new SortedResultSet( aWelcome.Old ); + mxOne = new SortedResultSet( aWelcome.New ); + mxOne->Initialize( maOptions, mxCompFac ); + mbGotWelcome = true; + mbUseOne = true; + pCurSet = mxOne.get(); + + aWelcome.Old = mxTwo.get(); + aWelcome.New = mxOne.get(); + + ListAction aWelcomeAction; + aWelcomeAction.ActionInfo <<= aWelcome; + aWelcomeAction.Position = 0; + aWelcomeAction.Count = 0; + aWelcomeAction.ListActionType = ListActionType::WELCOME; + + maActions.Insert( aWelcomeAction ); + } + else + { + // throw RuntimeException(); + } + break; + } + case ListActionType::INSERTED: + { + pCurSet->InsertNew( aAction.Position, aAction.Count ); + bHasNew = true; + break; + } + case ListActionType::REMOVED: + { + pCurSet->Remove( aAction.Position, + aAction.Count, + &maActions ); + break; + } + case ListActionType::MOVED: + { + sal_Int32 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 = 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 SortedDynamicResultSet::impl_disposing() +{ + mxListener.clear(); + mxOriginal.clear(); +} + +// private methods + +void SortedDynamicResultSet::SendNotify() +{ + sal_Int32 nCount = maActions.Count(); + + if ( nCount && mxListener.is() ) + { + Sequence< ListAction > aActionList( maActions.Count() ); + ListAction *pActionList = aActionList.getArray(); + + for ( sal_Int32 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< XComponentContext > & rxContext ) +{ + m_xContext = rxContext; +} + + +SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory() +{ +} + + +// XServiceInfo methods. + +OUString SAL_CALL SortedDynamicResultSetFactory::getImplementationName() +{ + return "com.sun.star.comp.ucb.SortedDynamicResultSetFactory"; +} + +sal_Bool SAL_CALL SortedDynamicResultSetFactory::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSetFactory::getSupportedServiceNames() +{ + return { "com.sun.star.ucb.SortedDynamicResultSetFactory" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +ucb_SortedDynamicResultSetFactory_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new SortedDynamicResultSetFactory(context)); +} + +// SortedDynamicResultSetFactory methods. + +Reference< XDynamicResultSet > SAL_CALL +SortedDynamicResultSetFactory::createSortedDynamicResultSet( + const Reference< XDynamicResultSet > & Source, + const Sequence< NumberedSortingInfo > & Info, + const Reference< XAnyCompareFactory > & CompareFactory ) +{ + Reference< XDynamicResultSet > xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, m_xContext ); + return xRet; +} + +// EventList + +void EventList::Clear() +{ + maData.clear(); +} + +void EventList::AddEvent( sal_IntPtr nType, sal_Int32 nPos ) +{ + ListAction aAction; + aAction.Position = nPos; + aAction.Count = 1; + aAction.ListActionType = nType; + + Insert( aAction ); +} + +// SortedDynamicResultSetListener + +SortedDynamicResultSetListener::SortedDynamicResultSetListener( + SortedDynamicResultSet *mOwner ) +{ + mpOwner = mOwner; +} + + +SortedDynamicResultSetListener::~SortedDynamicResultSetListener() +{ +} + +// XEventListener ( base of XDynamicResultSetListener ) + +void SAL_CALL +SortedDynamicResultSetListener::disposing( const EventObject& /*Source*/ ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_disposing(); +} + + +// XDynamicResultSetListener + +void SAL_CALL +SortedDynamicResultSetListener::notify( const ListEvent& Changes ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpOwner ) + mpOwner->impl_notify( Changes ); +} + +// own methods: + +void +SortedDynamicResultSetListener::impl_OwnerDies() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mpOwner = nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/sorter/sortdynres.hxx b/ucb/source/sorter/sortdynres.hxx new file mode 100644 index 000000000..1098f223a --- /dev/null +++ b/ucb/source/sorter/sortdynres.hxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#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/XSortedDynamicResultSetFactory.hpp> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase.hxx> +#include <memory> +#include "sortresult.hxx" + + + +class SortedDynamicResultSetListener; + +class SortedDynamicResultSet: public cppu::WeakImplHelper < + css::lang::XServiceInfo, + css::ucb::XDynamicResultSet > +{ + std::unique_ptr<comphelper::OInterfaceContainerHelper3<css::lang::XEventListener>> mpDisposeEventListeners; + + css::uno::Reference < css::ucb::XDynamicResultSetListener > mxListener; + + css::uno::Reference < css::ucb::XDynamicResultSet > mxOriginal; + css::uno::Sequence < css::ucb::NumberedSortingInfo > maOptions; + css::uno::Reference < css::ucb::XAnyCompareFactory > mxCompFac; + css::uno::Reference < css::uno::XComponentContext > m_xContext; + + rtl::Reference<SortedResultSet> mxOne; + rtl::Reference<SortedResultSet> mxTwo; + rtl::Reference<SortedDynamicResultSetListener> mxOwnListener; + + EventList maActions; + osl::Mutex maMutex; + bool mbGotWelcome:1; + bool mbUseOne:1; + bool mbStatic:1; + +private: + void SendNotify(); + +public: + SortedDynamicResultSet( const css::uno::Reference < css::ucb::XDynamicResultSet > &xOriginal, + const css::uno::Sequence < css::ucb::NumberedSortingInfo > &aOptions, + const css::uno::Reference < css::ucb::XAnyCompareFactory > &xCompFac, + const css::uno::Reference < css::uno::XComponentContext > &rxContext ); + + virtual ~SortedDynamicResultSet() override; + + + // XServiceInfo + + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + + virtual void SAL_CALL dispose() override; + + virtual void SAL_CALL + addEventListener( const css::uno::Reference< css::lang::XEventListener >& Listener ) override; + + virtual void SAL_CALL + removeEventListener( const css::uno::Reference< css::lang::XEventListener >& Listener ) override; + + + // XDynamicResultSet + + virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getStaticResultSet() override; + + virtual void SAL_CALL + setListener( const css::uno::Reference< css::ucb::XDynamicResultSetListener >& Listener ) override; + + virtual void SAL_CALL + connectToCache( const css::uno::Reference< css::ucb::XDynamicResultSet > & xCache ) override; + + virtual sal_Int16 SAL_CALL + getCapabilities() override; + + + // own methods: + + /// @throws css::uno::RuntimeException + void impl_disposing(); + + /// @throws css::uno::RuntimeException + void impl_notify( const css::ucb::ListEvent& Changes ); +}; + +class SortedDynamicResultSetListener: public cppu::WeakImplHelper < + css::ucb::XDynamicResultSetListener > +{ + SortedDynamicResultSet *mpOwner; + osl::Mutex maMutex; + +public: + SortedDynamicResultSetListener( SortedDynamicResultSet *mOwner ); + virtual ~SortedDynamicResultSetListener() override; + + // XEventListener ( base of XDynamicResultSetListener ) + + virtual void SAL_CALL + disposing( const css::lang::EventObject& Source ) override; + + // XDynamicResultSetListener + + virtual void SAL_CALL notify( const css::ucb::ListEvent& Changes ) override; + + // own methods: + + void impl_OwnerDies(); +}; + + +class SortedDynamicResultSetFactory: public cppu::WeakImplHelper < + css::lang::XServiceInfo, + css::ucb::XSortedDynamicResultSetFactory > +{ + + css::uno::Reference< css::uno::XComponentContext > m_xContext; + +public: + SortedDynamicResultSetFactory( + const css::uno::Reference< css::uno::XComponentContext > & rxContext); + + virtual ~SortedDynamicResultSetFactory() override; + + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XSortedDynamicResultSetFactory + virtual css::uno::Reference< css::ucb::XDynamicResultSet > SAL_CALL + createSortedDynamicResultSet( + const css::uno::Reference< css::ucb::XDynamicResultSet > & Source, + const css::uno::Sequence< css::ucb::NumberedSortingInfo > & Info, + const css::uno::Reference< css::ucb::XAnyCompareFactory > & CompareFactory ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/sorter/sortresult.cxx b/ucb/source/sorter/sortresult.cxx new file mode 100644 index 000000000..e5b7ce746 --- /dev/null +++ b/ucb/source/sorter/sortresult.cxx @@ -0,0 +1,1778 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "sortresult.hxx" +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/ucb/ListActionType.hpp> +#include <com/sun/star/ucb/XAnyCompare.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <tools/diagnose_ex.h> +#include <memory> + +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 comphelper; +using namespace cppu; + + +// The mutex to synchronize access to containers. +static osl::Mutex& getContainerMutex() +{ + static osl::Mutex ourMutex; + + return ourMutex; +} + + +struct SortInfo +{ + bool mbUseOwnCompare; + bool mbAscending; + bool mbCaseSensitive; + sal_Int32 mnColumn; + sal_Int32 mnType; + SortInfo* mpNext; + Reference < XAnyCompare > mxCompareFunction; +}; + + +struct SortListData +{ + bool mbModified; + sal_IntPtr mnCurPos; + sal_IntPtr mnOldPos; + + explicit SortListData( sal_IntPtr nPos ); +}; + + + + +class SRSPropertySetInfo : public cppu::WeakImplHelper < + XPropertySetInfo > +{ + Property maProps[2]; + +private: + +public: + SRSPropertySetInfo(); + + // XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties() override; + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override; + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override; +}; + + +SortedResultSet::SortedResultSet( Reference< XResultSet > const & aResult ) +{ + mpDisposeEventListeners = nullptr; + mpPropChangeListeners = nullptr; + mpVetoChangeListeners = nullptr; + + mxOriginal = aResult; + mpSortInfo = nullptr; + mnLastSort = 0; + mnCurEntry = 0; + mnCount = 0; + mbIsCopy = false; +} + + +SortedResultSet::~SortedResultSet() +{ + mxOriginal.clear(); + mxOther.clear(); + + if ( !mbIsCopy ) + { + SortInfo *pInfo = mpSortInfo; + while ( pInfo ) + { + mpSortInfo = pInfo->mpNext; + delete pInfo; + pInfo = mpSortInfo; + } + } + + mpSortInfo = nullptr; + + mpPropSetInfo.clear(); +} + + +// XServiceInfo methods. + +OUString SAL_CALL SortedResultSet::getImplementationName() +{ + return "com.sun.star.comp.ucb.SortedResultSet"; +} + +sal_Bool SAL_CALL SortedResultSet::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +css::uno::Sequence< OUString > SAL_CALL SortedResultSet::getSupportedServiceNames() +{ + return { RESULTSET_SERVICE_NAME }; +} + + +// XComponent methods. + +void SAL_CALL SortedResultSet::dispose() +{ + 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 ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpDisposeEventListeners ) + mpDisposeEventListeners = + new OInterfaceContainerHelper3<XEventListener>( getContainerMutex() ); + + mpDisposeEventListeners->addInterface( Listener ); +} + + +void SAL_CALL SortedResultSet::removeEventListener( + const Reference< XEventListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpDisposeEventListeners ) + mpDisposeEventListeners->removeInterface( Listener ); +} + + +// XContentAccess methods. + + +OUString SAL_CALL +SortedResultSet::queryContentIdentifierString() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifierString(); +} + + +Reference< XContentIdentifier > SAL_CALL +SortedResultSet::queryContentIdentifier() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifier(); +} + + +Reference< XContent > SAL_CALL +SortedResultSet::queryContent() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XContentAccess >::query(mxOriginal)->queryContent(); +} + + +// XResultSet methods. + +sal_Bool SAL_CALL SortedResultSet::next() +{ + 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 false; +} + + +sal_Bool SAL_CALL SortedResultSet::isBeforeFirst() +{ + if ( mnCurEntry ) + return false; + else + return true; +} + + +sal_Bool SAL_CALL SortedResultSet::isAfterLast() +{ + if ( mnCurEntry > mnCount ) + return true; + else + return false; +} + + +sal_Bool SAL_CALL SortedResultSet::isFirst() +{ + if ( mnCurEntry == 1 ) + return true; + else + return false; +} + + +sal_Bool SAL_CALL SortedResultSet::isLast() +{ + if ( mnCurEntry == mnCount ) + return true; + else + return false; +} + + +void SAL_CALL SortedResultSet::beforeFirst() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = 0; + mxOriginal->beforeFirst(); +} + + +void SAL_CALL SortedResultSet::afterLast() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + mnCurEntry = mnCount+1; + mxOriginal->afterLast(); +} + + +sal_Bool SAL_CALL SortedResultSet::first() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = 1; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return false; + } +} + + +sal_Bool SAL_CALL SortedResultSet::last() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mnCount ) + { + mnCurEntry = mnCount; + sal_Int32 nIndex = maS2O[ mnCurEntry ]; + return mxOriginal->absolute( nIndex ); + } + else + { + mnCurEntry = 0; + return false; + } +} + + +sal_Int32 SAL_CALL SortedResultSet::getRow() +{ + 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 + <TRUE/> if the cursor is on a row; <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 ) +{ + 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 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 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 + <TRUE/> if the cursor is on a valid row; <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 ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + if ( rows == 0 ) + return true; + + sal_Int32 nTmp = mnCurEntry + rows; + + if ( nTmp <= 0 ) + { + mnCurEntry = 0; + return false; + } + else if ( nTmp > mnCount ) + { + mnCurEntry = mnCount + 1; + return 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 <TRUE/> if the cursor is on a valid row; <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() +{ + 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 false; +} + + +void SAL_CALL SortedResultSet::refreshRow() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + mxOriginal->refreshRow(); +} + + +sal_Bool SAL_CALL SortedResultSet::rowUpdated() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowUpdated(); +} + + +sal_Bool SAL_CALL SortedResultSet::rowInserted() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowInserted(); +} + + +sal_Bool SAL_CALL SortedResultSet::rowDeleted() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->rowDeleted(); +} + + +Reference< XInterface > SAL_CALL SortedResultSet::getStatement() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) ) + { + throw SQLException(); + } + + return mxOriginal->getStatement(); +} + + +// XRow methods. + + +sal_Bool SAL_CALL SortedResultSet::wasNull() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->wasNull(); +} + + +OUString SAL_CALL SortedResultSet::getString( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getString( columnIndex ); +} + + +sal_Bool SAL_CALL SortedResultSet::getBoolean( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBoolean( columnIndex ); +} + + +sal_Int8 SAL_CALL SortedResultSet::getByte( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getByte( columnIndex ); +} + + +sal_Int16 SAL_CALL SortedResultSet::getShort( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getShort( columnIndex ); +} + + +sal_Int32 SAL_CALL SortedResultSet::getInt( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getInt( columnIndex ); +} + +sal_Int64 SAL_CALL SortedResultSet::getLong( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getLong( columnIndex ); +} + + +float SAL_CALL SortedResultSet::getFloat( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getFloat( columnIndex ); +} + + +double SAL_CALL SortedResultSet::getDouble( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDouble( columnIndex ); +} + + +Sequence< sal_Int8 > SAL_CALL SortedResultSet::getBytes( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBytes( columnIndex ); +} + + +Date SAL_CALL SortedResultSet::getDate( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getDate( columnIndex ); +} + + +Time SAL_CALL SortedResultSet::getTime( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTime( columnIndex ); +} + + +DateTime SAL_CALL SortedResultSet::getTimestamp( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getTimestamp( columnIndex ); +} + + +Reference< XInputStream > SAL_CALL +SortedResultSet::getBinaryStream( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBinaryStream( columnIndex ); +} + + +Reference< XInputStream > SAL_CALL +SortedResultSet::getCharacterStream( sal_Int32 columnIndex ) +{ + 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 ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getObject( columnIndex, + typeMap); +} + + +Reference< XRef > SAL_CALL SortedResultSet::getRef( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getRef( columnIndex ); +} + + +Reference< XBlob > SAL_CALL SortedResultSet::getBlob( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getBlob( columnIndex ); +} + + +Reference< XClob > SAL_CALL SortedResultSet::getClob( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getClob( columnIndex ); +} + + +Reference< XArray > SAL_CALL SortedResultSet::getArray( sal_Int32 columnIndex ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XRow >::query(mxOriginal)->getArray( columnIndex ); +} + + +// XCloseable methods. + + +void SAL_CALL SortedResultSet::close() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + Reference< XCloseable >::query(mxOriginal)->close(); +} + + +// XResultSetMetaDataSupplier methods. + + +Reference< XResultSetMetaData > SAL_CALL SortedResultSet::getMetaData() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + return Reference< XResultSetMetaDataSupplier >::query(mxOriginal)->getMetaData(); +} + + +// XPropertySet methods. + + +Reference< XPropertySetInfo > SAL_CALL +SortedResultSet::getPropertySetInfo() +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropSetInfo.is() ) + { + mpPropSetInfo = new SRSPropertySetInfo(); + } + + return mpPropSetInfo; +} + + +void SAL_CALL SortedResultSet::setPropertyValue( + const OUString& PropertyName, + const Any& ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( PropertyName == "RowCount" || PropertyName == "IsRowCountFinal" ) + throw IllegalArgumentException(); + else + throw UnknownPropertyException(PropertyName); +} + + +Any SAL_CALL SortedResultSet::getPropertyValue( const OUString& PropertyName ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + Any aRet; + + if ( PropertyName == "RowCount" ) + { + aRet <<= maS2O.Count(); + } + else if ( PropertyName == "IsRowCountFinal" ) + { + bool bOrgFinal = false; + Any aOrgRet; + + aRet <<= false; + + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue( PropertyName ); + aOrgRet >>= bOrgFinal; + + if ( bOrgFinal ) + { + aOrgRet = Reference< XPropertySet >::query(mxOriginal)-> + getPropertyValue("RowCount"); + sal_uInt32 nOrgCount = 0; + aOrgRet >>= nOrgCount; + if ( nOrgCount == maS2O.Count() ) + aRet <<= true; + } + } + else + throw UnknownPropertyException(PropertyName); + + return aRet; +} + + +void SAL_CALL SortedResultSet::addPropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + mpPropChangeListeners.reset( + new comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertyChangeListener, OUString>(getContainerMutex()) ); + + mpPropChangeListeners->addInterface( PropertyName, Listener ); +} + + +void SAL_CALL SortedResultSet::removePropertyChangeListener( + const OUString& PropertyName, + const Reference< XPropertyChangeListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpPropChangeListeners ) + mpPropChangeListeners->removeInterface( PropertyName, Listener ); +} + + +void SAL_CALL SortedResultSet::addVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpVetoChangeListeners ) + mpVetoChangeListeners.reset( + new comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XVetoableChangeListener, OUString>(getContainerMutex()) ); + + mpVetoChangeListeners->addInterface( PropertyName, Listener ); +} + + +void SAL_CALL SortedResultSet::removeVetoableChangeListener( + const OUString& PropertyName, + const Reference< XVetoableChangeListener >& Listener ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( mpVetoChangeListeners ) + mpVetoChangeListeners->removeInterface( PropertyName, Listener ); +} + + +// private methods + +sal_Int32 SortedResultSet::CompareImpl( const Reference < XResultSet >& xResultOne, + const Reference < XResultSet >& xResultTwo, + sal_Int32 nIndexOne, sal_Int32 nIndexTwo, + SortInfo const * pSortInfo ) +{ + Reference < XRow > xRowOne( xResultOne, UNO_QUERY ); + Reference < XRow > xRowTwo( xResultTwo, UNO_QUERY ); + + sal_IntPtr nCompare = 0; + sal_Int32 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 = static_cast<sal_Int32>(aTwo.Year) - static_cast<sal_Int32>(aOne.Year); + if ( !nTmp ) { + nTmp = static_cast<sal_Int32>(aTwo.Month) - static_cast<sal_Int32>(aOne.Month); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Day) - static_cast<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 = static_cast<sal_Int32>(aTwo.Hours) - static_cast<sal_Int32>(aOne.Hours); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Minutes) - static_cast<sal_Int32>(aOne.Minutes); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Seconds) - static_cast<sal_Int32>(aOne.Seconds); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.NanoSeconds) + - static_cast<sal_Int32>(aOne.NanoSeconds); + + 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 = static_cast<sal_Int32>(aTwo.Year) - static_cast<sal_Int32>(aOne.Year); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Month) - static_cast<sal_Int32>(aOne.Month); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Day) - static_cast<sal_Int32>(aOne.Day); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Hours) - static_cast<sal_Int32>(aOne.Hours); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Minutes) - static_cast<sal_Int32>(aOne.Minutes); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.Seconds) - static_cast<sal_Int32>(aOne.Seconds); + if ( !nTmp ) + nTmp = static_cast<sal_Int32>(aTwo.NanoSeconds) + - static_cast<sal_Int32>(aOne.NanoSeconds); + + 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_FAIL( "DataType not supported for compare!" ); + } + } + + return nCompare; +} + + +sal_Int32 SortedResultSet::CompareImpl( const Reference < XResultSet >& xResultOne, + const Reference < XResultSet >& xResultTwo, + sal_Int32 nIndexOne, sal_Int32 nIndexTwo ) +{ + sal_IntPtr 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, nullptr ); + if ( xResultTwo->absolute( nIndexTwo ) ) + aTwo = xRowTwo->getObject( pInfo->mnColumn, nullptr ); + + nCompare = pInfo->mxCompareFunction->compare( aOne, aTwo ); + } + + if ( ! pInfo->mbAscending ) + nCompare = - nCompare; + + pInfo = pInfo->mpNext; + } + + return nCompare; +} + + +sal_Int32 SortedResultSet::Compare( SortListData const *pOne, + SortListData const *pTwo ) +{ + sal_IntPtr nIndexOne; + sal_IntPtr 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; + } + + sal_IntPtr nCompare; + nCompare = CompareImpl( xResultOne, xResultTwo, + nIndexOne, nIndexTwo ); + return nCompare; +} + + +sal_Int32 SortedResultSet::FindPos( SortListData const *pEntry, + sal_IntPtr _nStart, sal_IntPtr _nEnd ) +{ + if ( _nStart > _nEnd ) + return _nStart + 1; + + sal_IntPtr nStart = _nStart; + sal_IntPtr nEnd = _nEnd; + sal_IntPtr nMid = 0, nCompare = 0; + + + while ( nStart <= nEnd ) + { + nMid = ( nEnd - nStart ) / 2 + nStart; + SortListData *pMid = maS2O.GetData( nMid ); + nCompare = Compare( pEntry, pMid ); + + if ( !nCompare ) + nCompare = (pEntry != pMid) ? ((pEntry < pMid) ? -1 : 1) : 0; + + 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. + OInterfaceContainerHelper3<XPropertyChangeListener>* pPropsContainer = + mpPropChangeListeners->getContainer( rEvt.PropertyName ); + if ( pPropsContainer ) + pPropsContainer->notifyEach( &XPropertyChangeListener::propertyChange, rEvt ); + + // Notify listeners interested in all properties. + pPropsContainer = mpPropChangeListeners->getContainer( OUString() ); + if ( pPropsContainer ) + pPropsContainer->notifyEach( &XPropertyChangeListener::propertyChange, rEvt ); +} + + +// public methods + + +void SortedResultSet::CopyData( SortedResultSet *pSource ) +{ + const SortedEntryList& rSrcS2O = pSource->maS2O; + + sal_IntPtr i, nCount; + + maS2O.Clear(); + m_O2S.clear(); + m_ModList.clear(); + + maS2O.Insert( nullptr, 0 ); + m_O2S.push_back(0); + + nCount = rSrcS2O.Count(); + + for ( i=1; i<nCount; i++ ) + { + maS2O.Insert( std::unique_ptr<SortListData>(new SortListData( rSrcS2O[ i ] )), i ); + m_O2S.push_back(pSource->m_O2S[i]); + } + + mnLastSort = maS2O.Count(); + mxOther = pSource->mxOriginal; + + if ( !mpSortInfo ) + { + mpSortInfo = pSource->mpSortInfo; + mbIsCopy = true; + } +} + + +void SortedResultSet::Initialize( + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + BuildSortInfo( mxOriginal, xSortInfo, xCompFactory ); + // Insert dummy at pos 0 + maS2O.Insert( std::unique_ptr<SortListData>(new SortListData( 0 )), 0 ); + + sal_IntPtr 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 ) ) + { + std::unique_ptr<SortListData> pData(new SortListData( nIndex )); + sal_IntPtr nPos = FindPos( pData.get(), 1, nIndex-1 ); + + maS2O.Insert( std::move(pData), nPos ); + + nIndex++; + } + } + catch (const SQLException&) + { + TOOLS_WARN_EXCEPTION("ucb", ""); + } + + // when we have fetched all the elements, we can create the + // original to sorted mapping list from the s2o list + m_O2S.clear(); + m_O2S.push_back(0); + + // insert some dummy entries first and replace then + // the entries with the right ones + size_t i; + + for ( i=1; i<maS2O.Count(); i++ ) + m_O2S.push_back(0); + for ( i=1; i<maS2O.Count(); i++ ) + m_O2S[maS2O[i]] = i; + + mnCount = maS2O.Count() - 1; +} + + +void SortedResultSet::CheckProperties( sal_Int32 nOldCount, bool bWasFinal ) +{ + osl::Guard< osl::Mutex > aGuard( maMutex ); + + if ( !mpPropChangeListeners ) + return; + + try { + // check for propertyChangeEvents + if ( nOldCount != GetCount() ) + { + bool bIsFinal = false; + PropertyChangeEvent aEvt; + + aEvt.PropertyName = "RowCount"; + aEvt.Further = false; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= nOldCount; + aEvt.NewValue <<= GetCount(); + + PropertyChanged( aEvt ); + + OUString aName = "IsRowCountFinal"; + Any aRet = getPropertyValue( aName ); + if ( (aRet >>= bIsFinal) && bIsFinal != bWasFinal ) + { + aEvt.PropertyName = aName; + aEvt.Further = false; + aEvt.PropertyHandle = -1; + aEvt.OldValue <<= bWasFinal; + aEvt.NewValue <<= bIsFinal; + PropertyChanged( aEvt ); + } + } + } + catch (const UnknownPropertyException&) {} + catch (const WrappedTargetException&) {} +} + + +void SortedResultSet::InsertNew( sal_Int32 nPos, sal_Int32 nCount ) +{ + // for all entries in the msS20-list, which are >= nPos, increase by nCount + sal_IntPtr i, nEnd; + + nEnd = maS2O.Count(); + for ( i=1; i<=nEnd; i++ ) + { + SortListData *pData = maS2O.GetData( i ); + if ( pData->mnCurPos >= nPos ) + { + pData->mnCurPos += nCount; + } + } + + // and append the new entries at the end of the maS2O-list or insert at the + // position nPos in the maS2O-list + for ( i=0; i<nCount; i++ ) + { + nEnd += 1; + std::unique_ptr<SortListData> pData(new SortListData( nEnd )); + + maS2O.Insert( std::move(pData), nEnd ); // Insert( Value, Position ) + m_O2S.insert(m_O2S.begin() + nPos + i, nEnd); + } + + mnCount += nCount; +} + + +void SortedResultSet::Remove( sal_Int32 nPos, sal_Int32 nCount, EventList *pEvents ) +{ + sal_IntPtr 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 ( sal_IntPtr i=0; i < nCount; i++ ) + { + sal_IntPtr nSortPos = m_O2S[nPos]; + m_O2S.erase(m_O2S.begin() + nPos); + + for (size_t j=1; j < m_O2S.size(); ++j) + { + sal_IntPtr nVal = m_O2S[j]; + if ( nVal > nSortPos ) + { + --nVal; + m_O2S[j] = nVal; + } + } + + std::unique_ptr<SortListData> pData = maS2O.Remove( nSortPos ); + if ( pData->mbModified ) + m_ModList.erase(std::find(m_ModList.begin(), m_ModList.end(), pData.get())); + + // generate remove Event, but not for new entries + if ( nSortPos <= nOldLastSort ) + pEvents->AddEvent( ListActionType::REMOVED, nSortPos ); + } + + // correct the positions in the sorted list + for ( sal_uInt32 i=1; i<= maS2O.Count(); i++ ) + { + SortListData *pData = maS2O.GetData( i ); + if ( pData->mnCurPos > nPos ) + pData->mnCurPos -= nCount; + } + + mnCount -= nCount; +} + + +void SortedResultSet::Move( sal_Int32 nPos, sal_Int32 nCount, sal_Int32 nOffset ) +{ + if ( !nOffset ) + return; + + sal_IntPtr i, nSortPos, nTo; + SortListData *pData; + + for ( i=0; i<nCount; i++ ) + { + nSortPos = m_O2S[nPos + i]; + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nOffset; + } + + if ( nOffset < 0 ) + { + for ( i=nPos+nOffset; i<nPos; i++ ) + { + nSortPos = m_O2S[i]; + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos += nCount; + } + } + else + { + sal_IntPtr nStart = nPos + nCount; + sal_IntPtr nEnd = nStart + nOffset; + for ( i=nStart; i<nEnd; i++ ) + { + nSortPos = m_O2S[i]; + pData = maS2O.GetData( nSortPos ); + pData->mnCurPos -= nCount; + } + } + + // remember the to be moved entries + std::unique_ptr<sal_IntPtr[]> pTmpArr(new sal_IntPtr[ nCount ]); + for ( i=0; i<nCount; i++ ) + pTmpArr[i] = m_O2S[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 + sal_IntPtr nFrom = nPos - 1; + nTo = nPos + nCount - 1; + + // same for i here + for ( i=0; i>nOffset; i-- ) + { + sal_IntPtr const nVal = m_O2S[nFrom + i]; + m_O2S[nTo + i] = nVal; + } + + } + else + { + sal_IntPtr nStart = nPos + nCount; + for ( i=0; i<nOffset; i++ ) + { + sal_IntPtr const nVal = m_O2S[nStart + i]; + m_O2S[nPos + i] = nVal; + } + } + + // finally put the remembered entries at their new location + nTo = nPos + nOffset; + for ( i=0; i<nCount; i++ ) + { + m_O2S[nTo + i] = pTmpArr[i]; + } +} + + +void SortedResultSet::BuildSortInfo( + const Reference< XResultSet >& aResult, + const Sequence < NumberedSortingInfo > &xSortInfo, + const Reference< XAnyCompareFactory > &xCompFactory ) +{ + Reference < XResultSetMetaDataSupplier > xMeta ( aResult, UNO_QUERY ); + + if ( ! xMeta.is() ) + { + OSL_FAIL( "No MetaData, No Sorting!" ); + return; + } + + Reference < XResultSetMetaData > xData = xMeta->getMetaData(); + const NumberedSortingInfo *pSortInfo = xSortInfo.getConstArray(); + + sal_Int32 nColumn; + OUString aPropName; + SortInfo *pInfo; + + for ( sal_Int32 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 = false; + pInfo->mnType = 0; + } + else + { + pInfo->mbUseOwnCompare = 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( sal_Int32 nPos, sal_Int32 nCount ) +{ + for ( sal_IntPtr i=0; i<nCount; i++ ) + { + sal_IntPtr const nSortPos = m_O2S[nPos]; + if ( nSortPos < mnLastSort ) + { + SortListData *pData = maS2O.GetData( nSortPos ); + if ( ! pData->mbModified ) + { + pData->mbModified = true; + m_ModList.push_back(pData); + } + } + nPos += 1; + } +} + + +void SortedResultSet::ResortModified( EventList* pList ) +{ + sal_IntPtr nCompare, nCurPos, nNewPos; + sal_IntPtr nStart, nEnd, nOffset, nVal; + + try { + for (size_t i = 0; i < m_ModList.size(); ++i) + { + SortListData *const pData = m_ModList[i]; + nCompare = CompareImpl( mxOther, mxOriginal, + pData->mnOldPos, pData->mnCurPos ); + pData->mbModified = false; + if ( nCompare != 0 ) + { + nCurPos = m_O2S[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.Move( static_cast<sal_uInt32>(nCurPos), nNewPos ); + for (size_t j = 1; j < m_O2S.size(); ++j) + { + nVal = m_O2S[j]; + if ( ( nStart <= nVal ) && ( nVal <= nEnd ) ) + { + nVal += nOffset; + m_O2S[j] = nVal; + } + } + + m_O2S[pData->mnCurPos] = nNewPos; + + ListAction aAction; + aAction.Position = nCurPos; + aAction.Count = 1; + aAction.ListActionType = ListActionType::MOVED; + aAction.ActionInfo <<= nNewPos-nCurPos; + pList->Insert( aAction ); + } + pList->AddEvent( ListActionType::PROPERTIES_CHANGED, nNewPos ); + } + } + } + catch (const SQLException&) + { + TOOLS_WARN_EXCEPTION("ucb", ""); + } + + m_ModList.clear(); +} + + +void SortedResultSet::ResortNew( EventList* pList ) +{ + sal_IntPtr i, nNewPos, nVal; + + try { + for ( i = mnLastSort; i<static_cast<sal_IntPtr>(maS2O.Count()); i++ ) + { + SortListData *const pData = m_ModList[i]; + nNewPos = FindPos( pData, 1, mnLastSort ); + if ( nNewPos != i ) + { + maS2O.Move( static_cast<sal_uInt32>(i), nNewPos ); + for (size_t j=1; j< m_O2S.size(); ++j) + { + nVal = m_O2S[j]; + if ( nVal >= nNewPos ) + m_O2S[j] = nVal + 1; + } + m_O2S[pData->mnCurPos] = nNewPos; + } + mnLastSort++; + pList->AddEvent( ListActionType::INSERTED, nNewPos ); + } + } + catch (const SQLException&) + { + TOOLS_WARN_EXCEPTION("ucb", ""); + } +} + + +// SortListData + + +SortListData::SortListData( sal_IntPtr nPos ) + : mbModified(false) + , mnCurPos(nPos) + , mnOldPos(nPos) +{ +}; + +SortedEntryList::SortedEntryList() +{ +} + +SortedEntryList::~SortedEntryList() +{ +} + +void SortedEntryList::Clear() +{ + maData.clear(); +} + + +void SortedEntryList::Insert( std::unique_ptr<SortListData> pEntry, sal_Int32 nPos ) +{ + if ( nPos < static_cast<sal_IntPtr>(maData.size()) ) + maData.insert( maData.begin() + nPos, std::move(pEntry) ); + else + maData.push_back( std::move(pEntry) ); +} + +void SortedEntryList::Move( sal_Int32 nOldPos, sal_Int32 nNewPos ) +{ + auto p = std::move(maData[nOldPos]); + maData.erase( maData.begin() + nOldPos ); + maData.insert(maData.begin() + nNewPos, std::move(p)); +} + +std::unique_ptr<SortListData> SortedEntryList::Remove( sal_Int32 nPos ) +{ + std::unique_ptr<SortListData> pData; + + if ( nPos < static_cast<sal_IntPtr>(maData.size()) ) + { + pData = std::move(maData[ nPos ]); + maData.erase( maData.begin() + nPos ); + } + + return pData; +} + + +SortListData* SortedEntryList::GetData( sal_Int32 nPos ) +{ + SortListData *pData; + + if ( nPos < static_cast<sal_IntPtr>(maData.size()) ) + pData = maData[ nPos ].get(); + else + pData = nullptr; + + return pData; +} + + +sal_Int32 SortedEntryList::operator [] ( sal_Int32 nPos ) const +{ + SortListData *pData; + + if ( nPos < static_cast<sal_IntPtr>(maData.size()) ) + pData = maData[ nPos ].get(); + else + pData = nullptr; + + if ( pData ) + if ( ! pData->mbModified ) + return pData->mnCurPos; + else + { + OSL_FAIL( "SortedEntryList: Can't get value for modified entry!"); + return 0; + } + else + { + OSL_FAIL( "SortedEntryList: invalid pos!"); + return 0; + } +} + + +SRSPropertySetInfo::SRSPropertySetInfo() +{ + maProps[0].Name = "RowCount"; + maProps[0].Handle = -1; + maProps[0].Type = cppu::UnoType<OUString>::get(); + maProps[0].Attributes = -1; + + maProps[1].Name = "IsRowCountFinal"; + maProps[1].Handle = -1; + maProps[1].Type = cppu::UnoType<bool>::get(); + maProps[1].Attributes = -1; +} + +// XPropertySetInfo methods. + +Sequence< Property > SAL_CALL +SRSPropertySetInfo::getProperties() +{ + return Sequence < Property > ( maProps, 2 ); +} + + +Property SAL_CALL +SRSPropertySetInfo::getPropertyByName( const OUString& Name ) +{ + if ( Name == "RowCount" ) + return maProps[0]; + else if ( Name == "IsRowCountFinal" ) + return maProps[1]; + else + throw UnknownPropertyException(Name); +} + + +sal_Bool SAL_CALL +SRSPropertySetInfo::hasPropertyByName( const OUString& Name ) +{ + if ( Name == "RowCount" ) + return true; + else if ( Name == "IsRowCountFinal" ) + return true; + else + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/sorter/sortresult.hxx b/ucb/source/sorter/sortresult.hxx new file mode 100644 index 000000000..caf3d76e3 --- /dev/null +++ b/ucb/source/sorter/sortresult.hxx @@ -0,0 +1,329 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.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 <comphelper/multiinterfacecontainer3.hxx> +#include <comphelper/interfacecontainer3.hxx> +#include <cppuhelper/implbase.hxx> +#include <rtl/ref.hxx> +#include <deque> +#include <memory> + + +struct SortInfo; +struct SortListData; +class SRSPropertySetInfo; + + +class SortedEntryList +{ + std::deque < std::unique_ptr<SortListData> > maData; + +public: + SortedEntryList(); + ~SortedEntryList(); + + sal_uInt32 Count() const { return static_cast<sal_uInt32>(maData.size()); } + + void Clear(); + void Insert( std::unique_ptr<SortListData> pEntry, sal_Int32 nPos ); + std::unique_ptr<SortListData> Remove( sal_Int32 nPos ); + SortListData* GetData( sal_Int32 nPos ); + void Move( sal_Int32 nOldPos, sal_Int32 nNewPos ); + + sal_Int32 operator [] ( sal_Int32 nPos ) const; +}; + + +class EventList +{ + std::deque <css::ucb::ListAction > maData; + +public: + EventList(){} + + sal_uInt32 Count() const { return static_cast<sal_uInt32>(maData.size()); } + + void AddEvent( sal_IntPtr nType, sal_Int32 nPos ); + void Insert( const css::ucb::ListAction& rAction ) { maData.push_back( rAction ); } + void Clear(); + css::ucb::ListAction& GetAction( sal_Int32 nIndex ) { return maData[ nIndex ]; } +}; + + +inline constexpr OUStringLiteral RESULTSET_SERVICE_NAME = u"com.sun.star.ucb.SortedResultSet"; + + +class SortedResultSet: public cppu::WeakImplHelper < + css::lang::XServiceInfo, + css::lang::XComponent, + css::ucb::XContentAccess, + css::sdbc::XResultSet, + css::sdbc::XRow, + css::sdbc::XCloseable, + css::sdbc::XResultSetMetaDataSupplier, + css::beans::XPropertySet > +{ + comphelper::OInterfaceContainerHelper3<css::lang::XEventListener> *mpDisposeEventListeners; + std::unique_ptr<comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertyChangeListener, OUString>> mpPropChangeListeners; + std::unique_ptr<comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XVetoableChangeListener, OUString>> mpVetoChangeListeners; + + css::uno::Reference < css::sdbc::XResultSet > mxOriginal; + css::uno::Reference < css::sdbc::XResultSet > mxOther; + + rtl::Reference<SRSPropertySetInfo> mpPropSetInfo; + SortInfo* mpSortInfo; + osl::Mutex maMutex; + SortedEntryList maS2O; // maps the sorted entries to the original ones + std::deque<sal_IntPtr> m_O2S; /// maps the original Entries to the sorted ones + std::deque<SortListData*> m_ModList; /// keeps track of modified entries + sal_Int32 mnLastSort; // index of the last sorted entry; + sal_Int32 mnCurEntry; // index of the current entry + sal_Int32 mnCount; // total count of the elements + bool mbIsCopy; + + +private: + /// @throws css::sdbc::SQLException + /// @throws css::uno::RuntimeException + sal_Int32 FindPos( SortListData const *pEntry, sal_IntPtr nStart, sal_IntPtr nEnd ); + /// @throws css::sdbc::SQLException + /// @throws css::uno::RuntimeException + sal_Int32 Compare( SortListData const *pOne, + SortListData const *pTwo ); + void BuildSortInfo( const css::uno::Reference< css::sdbc::XResultSet >& aResult, + const css::uno::Sequence < css::ucb::NumberedSortingInfo > &xSortInfo, + const css::uno::Reference< css::ucb::XAnyCompareFactory > &xCompFac ); + /// @throws css::sdbc::SQLException + /// @throws css::uno::RuntimeException + static sal_Int32 CompareImpl( const css::uno::Reference < css::sdbc::XResultSet >& xResultOne, + const css::uno::Reference < css::sdbc::XResultSet >& xResultTwo, + sal_Int32 nIndexOne, sal_Int32 nIndexTwo, + SortInfo const * pSortInfo ); + /// @throws css::sdbc::SQLException + /// @throws css::uno::RuntimeException + sal_Int32 CompareImpl( const css::uno::Reference < css::sdbc::XResultSet >& xResultOne, + const css::uno::Reference < css::sdbc::XResultSet >& xResultTwo, + sal_Int32 nIndexOne, sal_Int32 nIndexTwo ); + void PropertyChanged( const css::beans::PropertyChangeEvent& rEvt ); + +public: + SortedResultSet( css::uno::Reference< css::sdbc::XResultSet > const & aResult ); + virtual ~SortedResultSet() override; + + sal_Int32 GetCount() const { return mnCount; } + + void CopyData( SortedResultSet* pSource ); + void Initialize( const css::uno::Sequence < css::ucb::NumberedSortingInfo > &xSortInfo, + const css::uno::Reference< css::ucb::XAnyCompareFactory > &xCompFac ); + void CheckProperties( sal_Int32 nOldCount, bool bWasFinal ); + + void InsertNew( sal_Int32 nPos, sal_Int32 nCount ); + void SetChanged( sal_Int32 nPos, sal_Int32 nCount ); + void Remove( sal_Int32 nPos, sal_Int32 nCount, EventList *pList ); + void Move( sal_Int32 nPos, sal_Int32 nCount, sal_Int32 nOffset ); + + void ResortModified( EventList* pList ); + void ResortNew( EventList* pList ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL + dispose() override; + + virtual void SAL_CALL + addEventListener( const css::uno::Reference< css::lang::XEventListener >& Listener ) override; + + virtual void SAL_CALL + removeEventListener( const css::uno::Reference< css::lang::XEventListener >& Listener ) override; + + // XContentAccess + virtual OUString SAL_CALL + queryContentIdentifierString() override; + virtual css::uno::Reference< + css::ucb::XContentIdentifier > SAL_CALL + queryContentIdentifier() override; + virtual css::uno::Reference< + css::ucb::XContent > SAL_CALL + queryContent() override; + + // XResultSet + virtual sal_Bool SAL_CALL + next() override; + virtual sal_Bool SAL_CALL + isBeforeFirst() override; + virtual sal_Bool SAL_CALL + isAfterLast() override; + virtual sal_Bool SAL_CALL + isFirst() override; + virtual sal_Bool SAL_CALL + isLast() override; + virtual void SAL_CALL + beforeFirst() override; + virtual void SAL_CALL + afterLast() override; + virtual sal_Bool SAL_CALL + first() override; + virtual sal_Bool SAL_CALL + last() override; + virtual sal_Int32 SAL_CALL + getRow() override; + virtual sal_Bool SAL_CALL + absolute( sal_Int32 row ) override; + virtual sal_Bool SAL_CALL + relative( sal_Int32 rows ) override; + virtual sal_Bool SAL_CALL + previous() override; + virtual void SAL_CALL + refreshRow() override; + virtual sal_Bool SAL_CALL + rowUpdated() override; + virtual sal_Bool SAL_CALL + rowInserted() override; + virtual sal_Bool SAL_CALL + rowDeleted() override; + virtual css::uno::Reference< + css::uno::XInterface > SAL_CALL + getStatement() override; + + // XRow + virtual sal_Bool SAL_CALL + wasNull() override; + + virtual OUString SAL_CALL + getString( sal_Int32 columnIndex ) override; + + virtual sal_Bool SAL_CALL + getBoolean( sal_Int32 columnIndex ) override; + + virtual sal_Int8 SAL_CALL + getByte( sal_Int32 columnIndex ) override; + + virtual sal_Int16 SAL_CALL + getShort( sal_Int32 columnIndex ) override; + + virtual sal_Int32 SAL_CALL + getInt( sal_Int32 columnIndex ) override; + + virtual sal_Int64 SAL_CALL + getLong( sal_Int32 columnIndex ) override; + + virtual float SAL_CALL + getFloat( sal_Int32 columnIndex ) override; + + virtual double SAL_CALL + getDouble( sal_Int32 columnIndex ) override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL + getBytes( sal_Int32 columnIndex ) override; + + virtual css::util::Date SAL_CALL + getDate( sal_Int32 columnIndex ) override; + + virtual css::util::Time SAL_CALL + getTime( sal_Int32 columnIndex ) override; + + virtual css::util::DateTime SAL_CALL + getTimestamp( sal_Int32 columnIndex ) override; + + virtual css::uno::Reference< + css::io::XInputStream > SAL_CALL + getBinaryStream( sal_Int32 columnIndex ) override; + + virtual css::uno::Reference< + css::io::XInputStream > SAL_CALL + getCharacterStream( sal_Int32 columnIndex ) override; + + virtual css::uno::Any SAL_CALL + getObject( sal_Int32 columnIndex, + const css::uno::Reference< + css::container::XNameAccess >& typeMap ) override; + virtual css::uno::Reference< + css::sdbc::XRef > SAL_CALL + getRef( sal_Int32 columnIndex ) override; + virtual css::uno::Reference< + css::sdbc::XBlob > SAL_CALL + getBlob( sal_Int32 columnIndex ) override; + virtual css::uno::Reference< + css::sdbc::XClob > SAL_CALL + getClob( sal_Int32 columnIndex ) override; + virtual css::uno::Reference< + css::sdbc::XArray > SAL_CALL + getArray( sal_Int32 columnIndex ) override; + + // XCloseable + virtual void SAL_CALL + close() override; + + // XResultSetMetaDataSupplier + virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL + getMetaData() override; + + + // XPropertySet + virtual css::uno::Reference< + css::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() override; + + virtual void SAL_CALL + setPropertyValue( const OUString& PropertyName, + const css::uno::Any& Value ) override; + + virtual css::uno::Any SAL_CALL + getPropertyValue( const OUString& PropertyName ) override; + + virtual void SAL_CALL + addPropertyChangeListener( const OUString& PropertyName, + const css::uno::Reference< + css::beans::XPropertyChangeListener >& Listener ) override; + + virtual void SAL_CALL + removePropertyChangeListener( const OUString& PropertyName, + const css::uno::Reference< + css::beans::XPropertyChangeListener >& Listener ) override; + + virtual void SAL_CALL + addVetoableChangeListener( const OUString& PropertyName, + const css::uno::Reference< + css::beans::XVetoableChangeListener >& Listener ) override; + + virtual void SAL_CALL + removeVetoableChangeListener( const OUString& PropertyName, + const css::uno::Reference< + css::beans::XVetoableChangeListener >& aListener ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/sorter/srtrs1.component b/ucb/source/sorter/srtrs1.component new file mode 100644 index 000000000..a96277d0b --- /dev/null +++ b/ucb/source/sorter/srtrs1.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.ucb.SortedDynamicResultSetFactory" + constructor="ucb_SortedDynamicResultSetFactory_get_implementation" single-instance="true"> + <service name="com.sun.star.ucb.SortedDynamicResultSetFactory"/> + </implementation> +</component> |