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