bump product version to 7.6.3.2-android
[LibreOffice.git] / ucb / source / sorter / sortresult.cxx
blob38b3c7583ed0837d107ae059a0bea8fef710550f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "sortresult.hxx"
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <com/sun/star/sdbc/SQLException.hpp>
24 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/XAnyCompare.hpp>
27 #include <cppuhelper/implbase.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <memory>
32 using namespace com::sun::star::beans;
33 using namespace com::sun::star::container;
34 using namespace com::sun::star::io;
35 using namespace com::sun::star::lang;
36 using namespace com::sun::star::sdbc;
37 using namespace com::sun::star::ucb;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::util;
40 using namespace comphelper;
41 using namespace cppu;
44 struct SortInfo
46 bool mbUseOwnCompare;
47 bool mbAscending;
48 bool mbCaseSensitive;
49 sal_Int32 mnColumn;
50 sal_Int32 mnType;
51 SortInfo* mpNext;
52 Reference < XAnyCompare > mxCompareFunction;
56 struct SortListData
58 bool mbModified;
59 sal_IntPtr mnCurPos;
60 sal_IntPtr mnOldPos;
62 explicit SortListData( sal_IntPtr nPos );
68 class SRSPropertySetInfo : public cppu::WeakImplHelper <
69 XPropertySetInfo >
71 Property maProps[2];
73 private:
75 public:
76 SRSPropertySetInfo();
78 // XPropertySetInfo
79 virtual Sequence< Property > SAL_CALL getProperties() override;
80 virtual Property SAL_CALL getPropertyByName( const OUString& aName ) override;
81 virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
85 SortedResultSet::SortedResultSet( Reference< XResultSet > const & aResult )
87 mxOriginal = aResult;
88 mpSortInfo = nullptr;
89 mnLastSort = 0;
90 mnCurEntry = 0;
91 mnCount = 0;
92 mbIsCopy = false;
96 SortedResultSet::~SortedResultSet()
98 mxOriginal.clear();
99 mxOther.clear();
101 if ( !mbIsCopy )
103 SortInfo *pInfo = mpSortInfo;
104 while ( pInfo )
106 mpSortInfo = pInfo->mpNext;
107 delete pInfo;
108 pInfo = mpSortInfo;
112 mpSortInfo = nullptr;
114 mpPropSetInfo.clear();
118 // XServiceInfo methods.
120 OUString SAL_CALL SortedResultSet::getImplementationName()
122 return "com.sun.star.comp.ucb.SortedResultSet";
125 sal_Bool SAL_CALL SortedResultSet::supportsService( const OUString& ServiceName )
127 return cppu::supportsService( this, ServiceName );
130 css::uno::Sequence< OUString > SAL_CALL SortedResultSet::getSupportedServiceNames()
132 return { RESULTSET_SERVICE_NAME };
136 // XComponent methods.
138 void SAL_CALL SortedResultSet::dispose()
140 std::unique_lock aGuard( maMutex );
142 if ( maDisposeEventListeners.getLength(aGuard) )
144 EventObject aEvt;
145 aEvt.Source = static_cast< XComponent * >( this );
146 maDisposeEventListeners.disposeAndClear( aGuard, aEvt );
149 if ( maPropChangeListeners.hasContainedTypes(aGuard) )
151 EventObject aEvt;
152 aEvt.Source = static_cast< XPropertySet * >( this );
153 maPropChangeListeners.disposeAndClear( aGuard, aEvt );
156 if ( maVetoChangeListeners.hasContainedTypes(aGuard) )
158 EventObject aEvt;
159 aEvt.Source = static_cast< XPropertySet * >( this );
160 maVetoChangeListeners.disposeAndClear( aGuard, aEvt );
163 mxOriginal.clear();
164 mxOther.clear();
168 void SAL_CALL SortedResultSet::addEventListener(
169 const Reference< XEventListener >& Listener )
171 std::unique_lock aGuard( maMutex );
173 maDisposeEventListeners.addInterface( aGuard, Listener );
177 void SAL_CALL SortedResultSet::removeEventListener(
178 const Reference< XEventListener >& Listener )
180 std::unique_lock aGuard( maMutex );
182 maDisposeEventListeners.removeInterface( aGuard, Listener );
186 // XContentAccess methods.
189 OUString SAL_CALL
190 SortedResultSet::queryContentIdentifierString()
192 std::unique_lock aGuard( maMutex );
193 return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifierString();
197 Reference< XContentIdentifier > SAL_CALL
198 SortedResultSet::queryContentIdentifier()
200 std::unique_lock aGuard( maMutex );
201 return Reference< XContentAccess >::query(mxOriginal)->queryContentIdentifier();
205 Reference< XContent > SAL_CALL
206 SortedResultSet::queryContent()
208 std::unique_lock aGuard( maMutex );
209 return Reference< XContentAccess >::query(mxOriginal)->queryContent();
213 // XResultSet methods.
215 sal_Bool SAL_CALL SortedResultSet::next()
217 std::unique_lock aGuard( maMutex );
219 mnCurEntry++;
221 if ( mnCurEntry > 0 )
223 if ( mnCurEntry <= mnCount )
225 sal_Int32 nIndex = maS2O[ mnCurEntry ];
226 return mxOriginal->absolute( nIndex );
228 else
230 mnCurEntry = mnCount + 1;
233 return false;
237 sal_Bool SAL_CALL SortedResultSet::isBeforeFirst()
239 if ( mnCurEntry )
240 return false;
241 else
242 return true;
246 sal_Bool SAL_CALL SortedResultSet::isAfterLast()
248 if ( mnCurEntry > mnCount )
249 return true;
250 else
251 return false;
255 sal_Bool SAL_CALL SortedResultSet::isFirst()
257 if ( mnCurEntry == 1 )
258 return true;
259 else
260 return false;
264 sal_Bool SAL_CALL SortedResultSet::isLast()
266 if ( mnCurEntry == mnCount )
267 return true;
268 else
269 return false;
273 void SAL_CALL SortedResultSet::beforeFirst()
275 std::unique_lock aGuard( maMutex );
276 mnCurEntry = 0;
277 mxOriginal->beforeFirst();
281 void SAL_CALL SortedResultSet::afterLast()
283 std::unique_lock aGuard( maMutex );
284 mnCurEntry = mnCount+1;
285 mxOriginal->afterLast();
289 sal_Bool SAL_CALL SortedResultSet::first()
291 std::unique_lock aGuard( maMutex );
293 if ( mnCount )
295 mnCurEntry = 1;
296 sal_Int32 nIndex = maS2O[ mnCurEntry ];
297 return mxOriginal->absolute( nIndex );
299 else
301 mnCurEntry = 0;
302 return false;
307 sal_Bool SAL_CALL SortedResultSet::last()
309 std::unique_lock aGuard( maMutex );
311 if ( mnCount )
313 mnCurEntry = mnCount;
314 sal_Int32 nIndex = maS2O[ mnCurEntry ];
315 return mxOriginal->absolute( nIndex );
317 else
319 mnCurEntry = 0;
320 return false;
325 sal_Int32 SAL_CALL SortedResultSet::getRow()
327 return mnCurEntry;
332 moves the cursor to the given row number in the result set.
333 <p>If the row number is positive, the cursor moves to the given row
334 number with respect to the beginning of the result set. The first
335 row is row 1, the second is row 2, and so on.
336 <p>If the given row number is negative, the cursor moves to an
337 absolute row position with respect to the end of the result set.
338 For example, calling <code>moveToPosition(-1)</code> positions the
339 cursor on the last row, <code>moveToPosition(-2)</code> indicates the
340 next-to-last row, and so on.
341 <p>An attempt to position the cursor beyond the first/last row in the
342 result set leaves the cursor before/after the first/last row,
343 respectively.
344 <p>Note: Calling <code>moveToPosition(1)</code> is the same
345 as calling <code>moveToFirst()</code>. Calling
346 <code>moveToPosition(-1)</code> is the same as calling
347 <code>moveToLast()</code>.
348 @param row
349 is the number of rows to move. Could be negative.
350 @returns
351 <TRUE/> if the cursor is on a row; <FALSE/> otherwise
352 @throws SQLException
353 if a database access error occurs or if row is 0, or the result set
354 type is FORWARD_ONLY.
356 sal_Bool SAL_CALL SortedResultSet::absolute( sal_Int32 row )
358 std::unique_lock aGuard( maMutex );
360 sal_Int32 nIndex;
362 if ( row > 0 )
364 if ( row <= mnCount )
366 mnCurEntry = row;
367 nIndex = maS2O[ mnCurEntry ];
368 return mxOriginal->absolute( nIndex );
370 else
372 mnCurEntry = mnCount + 1;
373 return false;
376 else if ( row == 0 )
378 throw SQLException();
380 else
382 if ( mnCount + row + 1 > 0 )
384 mnCurEntry = mnCount + row + 1;
385 nIndex = maS2O[ mnCurEntry ];
386 return mxOriginal->absolute( nIndex );
388 else
390 mnCurEntry = 0;
391 return false;
398 moves the cursor a relative number of rows, either positive or negative.
400 Attempting to move beyond the first/last row in the result set positions
401 the cursor before/after the first/last row. Calling
402 <code>moveRelative(0)</code> is valid, but does not change the cursor
403 position.
404 <p>Note: Calling <code>moveRelative(1)</code> is different from calling
405 <code>moveNext()</code> because is makes sense to call
406 <code>moveNext()</code> when there is no current row, for example,
407 when the cursor is positioned before the first row or after the last
408 row of the result set.
409 @param rows
410 is the number of rows to move. Could be negative.
411 @returns
412 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
413 the result set.
414 @throws SQLException
415 if a database access error occurs or if there is no
416 current row, or the result set type is FORWARD_ONLY.
418 sal_Bool SAL_CALL SortedResultSet::relative( sal_Int32 rows )
420 std::unique_lock aGuard( maMutex );
422 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
424 throw SQLException();
427 if ( rows == 0 )
428 return true;
430 sal_Int32 nTmp = mnCurEntry + rows;
432 if ( nTmp <= 0 )
434 mnCurEntry = 0;
435 return false;
437 else if ( nTmp > mnCount )
439 mnCurEntry = mnCount + 1;
440 return false;
442 else
444 mnCurEntry = nTmp;
445 nTmp = maS2O[ mnCurEntry ];
446 return mxOriginal->absolute( nTmp );
452 moves the cursor to the previous row in the result set.
453 <p>Note: <code>previous()</code> is not the same as
454 <code>relative(-1)</code> because it makes sense to call
455 <code>previous()</code> when there is no current row.
456 @returns <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
457 the result set.
458 @throws SQLException
459 if a database access error occurs or the result set type
460 is FORWARD_ONLY.
462 sal_Bool SAL_CALL SortedResultSet::previous()
464 std::unique_lock aGuard( maMutex );
466 mnCurEntry -= 1;
468 if ( mnCurEntry > 0 )
470 if ( mnCurEntry <= mnCount )
472 sal_Int32 nIndex = maS2O[ mnCurEntry ];
473 return mxOriginal->absolute( nIndex );
476 else
477 mnCurEntry = 0;
479 return false;
483 void SAL_CALL SortedResultSet::refreshRow()
485 std::unique_lock aGuard( maMutex );
487 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
489 throw SQLException();
492 mxOriginal->refreshRow();
496 sal_Bool SAL_CALL SortedResultSet::rowUpdated()
498 std::unique_lock aGuard( maMutex );
500 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
502 throw SQLException();
505 return mxOriginal->rowUpdated();
509 sal_Bool SAL_CALL SortedResultSet::rowInserted()
511 std::unique_lock aGuard( maMutex );
513 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
515 throw SQLException();
518 return mxOriginal->rowInserted();
522 sal_Bool SAL_CALL SortedResultSet::rowDeleted()
524 std::unique_lock aGuard( maMutex );
526 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
528 throw SQLException();
531 return mxOriginal->rowDeleted();
535 Reference< XInterface > SAL_CALL SortedResultSet::getStatement()
537 std::unique_lock aGuard( maMutex );
539 if ( ( mnCurEntry <= 0 ) || ( mnCurEntry > mnCount ) )
541 throw SQLException();
544 return mxOriginal->getStatement();
548 // XRow methods.
551 sal_Bool SAL_CALL SortedResultSet::wasNull()
553 std::unique_lock aGuard( maMutex );
554 return Reference< XRow >::query(mxOriginal)->wasNull();
558 OUString SAL_CALL SortedResultSet::getString( sal_Int32 columnIndex )
560 std::unique_lock aGuard( maMutex );
561 return Reference< XRow >::query(mxOriginal)->getString( columnIndex );
565 sal_Bool SAL_CALL SortedResultSet::getBoolean( sal_Int32 columnIndex )
567 std::unique_lock aGuard( maMutex );
568 return Reference< XRow >::query(mxOriginal)->getBoolean( columnIndex );
572 sal_Int8 SAL_CALL SortedResultSet::getByte( sal_Int32 columnIndex )
574 std::unique_lock aGuard( maMutex );
575 return Reference< XRow >::query(mxOriginal)->getByte( columnIndex );
579 sal_Int16 SAL_CALL SortedResultSet::getShort( sal_Int32 columnIndex )
581 std::unique_lock aGuard( maMutex );
582 return Reference< XRow >::query(mxOriginal)->getShort( columnIndex );
586 sal_Int32 SAL_CALL SortedResultSet::getInt( sal_Int32 columnIndex )
588 std::unique_lock aGuard( maMutex );
589 return Reference< XRow >::query(mxOriginal)->getInt( columnIndex );
592 sal_Int64 SAL_CALL SortedResultSet::getLong( sal_Int32 columnIndex )
594 std::unique_lock aGuard( maMutex );
595 return Reference< XRow >::query(mxOriginal)->getLong( columnIndex );
599 float SAL_CALL SortedResultSet::getFloat( sal_Int32 columnIndex )
601 std::unique_lock aGuard( maMutex );
602 return Reference< XRow >::query(mxOriginal)->getFloat( columnIndex );
606 double SAL_CALL SortedResultSet::getDouble( sal_Int32 columnIndex )
608 std::unique_lock aGuard( maMutex );
609 return Reference< XRow >::query(mxOriginal)->getDouble( columnIndex );
613 Sequence< sal_Int8 > SAL_CALL SortedResultSet::getBytes( sal_Int32 columnIndex )
615 std::unique_lock aGuard( maMutex );
616 return Reference< XRow >::query(mxOriginal)->getBytes( columnIndex );
620 Date SAL_CALL SortedResultSet::getDate( sal_Int32 columnIndex )
622 std::unique_lock aGuard( maMutex );
623 return Reference< XRow >::query(mxOriginal)->getDate( columnIndex );
627 Time SAL_CALL SortedResultSet::getTime( sal_Int32 columnIndex )
629 std::unique_lock aGuard( maMutex );
630 return Reference< XRow >::query(mxOriginal)->getTime( columnIndex );
634 DateTime SAL_CALL SortedResultSet::getTimestamp( sal_Int32 columnIndex )
636 std::unique_lock aGuard( maMutex );
637 return Reference< XRow >::query(mxOriginal)->getTimestamp( columnIndex );
641 Reference< XInputStream > SAL_CALL
642 SortedResultSet::getBinaryStream( sal_Int32 columnIndex )
644 std::unique_lock aGuard( maMutex );
645 return Reference< XRow >::query(mxOriginal)->getBinaryStream( columnIndex );
649 Reference< XInputStream > SAL_CALL
650 SortedResultSet::getCharacterStream( sal_Int32 columnIndex )
652 std::unique_lock aGuard( maMutex );
653 return Reference< XRow >::query(mxOriginal)->getCharacterStream( columnIndex );
657 Any SAL_CALL SortedResultSet::getObject( sal_Int32 columnIndex,
658 const Reference< XNameAccess >& typeMap )
660 std::unique_lock aGuard( maMutex );
661 return Reference< XRow >::query(mxOriginal)->getObject( columnIndex,
662 typeMap);
666 Reference< XRef > SAL_CALL SortedResultSet::getRef( sal_Int32 columnIndex )
668 std::unique_lock aGuard( maMutex );
669 return Reference< XRow >::query(mxOriginal)->getRef( columnIndex );
673 Reference< XBlob > SAL_CALL SortedResultSet::getBlob( sal_Int32 columnIndex )
675 std::unique_lock aGuard( maMutex );
676 return Reference< XRow >::query(mxOriginal)->getBlob( columnIndex );
680 Reference< XClob > SAL_CALL SortedResultSet::getClob( sal_Int32 columnIndex )
682 std::unique_lock aGuard( maMutex );
683 return Reference< XRow >::query(mxOriginal)->getClob( columnIndex );
687 Reference< XArray > SAL_CALL SortedResultSet::getArray( sal_Int32 columnIndex )
689 std::unique_lock aGuard( maMutex );
690 return Reference< XRow >::query(mxOriginal)->getArray( columnIndex );
694 // XCloseable methods.
697 void SAL_CALL SortedResultSet::close()
699 std::unique_lock aGuard( maMutex );
700 Reference< XCloseable >::query(mxOriginal)->close();
704 // XResultSetMetaDataSupplier methods.
707 Reference< XResultSetMetaData > SAL_CALL SortedResultSet::getMetaData()
709 std::unique_lock aGuard( maMutex );
710 return Reference< XResultSetMetaDataSupplier >::query(mxOriginal)->getMetaData();
714 // XPropertySet methods.
717 Reference< XPropertySetInfo > SAL_CALL
718 SortedResultSet::getPropertySetInfo()
720 std::unique_lock aGuard( maMutex );
722 if ( !mpPropSetInfo.is() )
724 mpPropSetInfo = new SRSPropertySetInfo();
727 return mpPropSetInfo;
731 void SAL_CALL SortedResultSet::setPropertyValue(
732 const OUString& PropertyName,
733 const Any& )
735 if ( PropertyName == "RowCount" || PropertyName == "IsRowCountFinal" )
736 throw IllegalArgumentException();
737 else
738 throw UnknownPropertyException(PropertyName);
742 Any SAL_CALL SortedResultSet::getPropertyValue( const OUString& PropertyName )
744 std::unique_lock aGuard( maMutex );
746 Any aRet;
748 if ( PropertyName == "RowCount" )
750 aRet <<= maS2O.Count();
752 else if ( PropertyName == "IsRowCountFinal" )
754 bool bOrgFinal = false;
755 Any aOrgRet;
757 aRet <<= false;
759 aOrgRet = Reference< XPropertySet >::query(mxOriginal)->
760 getPropertyValue( PropertyName );
761 aOrgRet >>= bOrgFinal;
763 if ( bOrgFinal )
765 aOrgRet = Reference< XPropertySet >::query(mxOriginal)->
766 getPropertyValue("RowCount");
767 sal_uInt32 nOrgCount = 0;
768 aOrgRet >>= nOrgCount;
769 if ( nOrgCount == maS2O.Count() )
770 aRet <<= true;
773 else
774 throw UnknownPropertyException(PropertyName);
776 return aRet;
780 void SAL_CALL SortedResultSet::addPropertyChangeListener(
781 const OUString& PropertyName,
782 const Reference< XPropertyChangeListener >& Listener )
784 std::unique_lock aGuard( maMutex );
786 maPropChangeListeners.addInterface( aGuard, PropertyName, Listener );
790 void SAL_CALL SortedResultSet::removePropertyChangeListener(
791 const OUString& PropertyName,
792 const Reference< XPropertyChangeListener >& Listener )
794 std::unique_lock aGuard( maMutex );
796 maPropChangeListeners.removeInterface( aGuard, PropertyName, Listener );
800 void SAL_CALL SortedResultSet::addVetoableChangeListener(
801 const OUString& PropertyName,
802 const Reference< XVetoableChangeListener >& Listener )
804 std::unique_lock aGuard( maMutex );
806 maVetoChangeListeners.addInterface( aGuard, PropertyName, Listener );
810 void SAL_CALL SortedResultSet::removeVetoableChangeListener(
811 const OUString& PropertyName,
812 const Reference< XVetoableChangeListener >& Listener )
814 std::unique_lock aGuard( maMutex );
816 maVetoChangeListeners.removeInterface( aGuard, PropertyName, Listener );
820 // private methods
822 sal_Int32 SortedResultSet::CompareImpl( const Reference < XResultSet >& xResultOne,
823 const Reference < XResultSet >& xResultTwo,
824 sal_Int32 nIndexOne, sal_Int32 nIndexTwo,
825 SortInfo const * pSortInfo )
827 Reference < XRow > xRowOne( xResultOne, UNO_QUERY );
828 Reference < XRow > xRowTwo( xResultTwo, UNO_QUERY );
830 sal_IntPtr nCompare = 0;
831 sal_Int32 nColumn = pSortInfo->mnColumn;
833 switch ( pSortInfo->mnType )
835 case DataType::BIT :
836 case DataType::TINYINT :
837 case DataType::SMALLINT :
838 case DataType::INTEGER :
840 sal_Int32 aOne = 0;
841 sal_Int32 aTwo = 0;
843 if ( xResultOne->absolute( nIndexOne ) )
844 aOne = xRowOne->getInt( nColumn );
845 if ( xResultTwo->absolute( nIndexTwo ) )
846 aTwo = xRowTwo->getInt( nColumn );
848 if ( aOne < aTwo )
849 nCompare = -1;
850 else if ( aOne == aTwo )
851 nCompare = 0;
852 else
853 nCompare = 1;
855 break;
857 case DataType::BIGINT :
859 sal_Int64 aOne = 0;
860 sal_Int64 aTwo = 0;
862 if ( xResultOne->absolute( nIndexOne ) )
863 aOne = xRowOne->getLong( nColumn );
864 if ( xResultTwo->absolute( nIndexTwo ) )
865 aTwo = xRowTwo->getLong( nColumn );
867 if ( aOne < aTwo )
868 nCompare = -1;
869 else if ( aOne == aTwo )
870 nCompare = 0;
871 else
872 nCompare = 1;
874 break;
876 case DataType::CHAR :
877 case DataType::VARCHAR :
878 case DataType::LONGVARCHAR :
880 OUString aOne, aTwo;
882 if ( xResultOne->absolute( nIndexOne ) )
883 aOne = xRowOne->getString( nColumn );
884 if ( xResultTwo->absolute( nIndexTwo ) )
885 aTwo = xRowTwo->getString( nColumn );
887 if ( ! pSortInfo->mbCaseSensitive )
889 aOne = aOne.toAsciiLowerCase();
890 aTwo = aTwo.toAsciiLowerCase();
893 nCompare = aOne.compareTo( aTwo );
894 break;
896 case DataType::DATE :
898 Date aOne, aTwo;
899 sal_Int32 nTmp;
901 if ( xResultOne->absolute( nIndexOne ) )
902 aOne = xRowOne->getDate( nColumn );
903 if ( xResultTwo->absolute( nIndexTwo ) )
904 aTwo = xRowTwo->getDate( nColumn );
906 nTmp = static_cast<sal_Int32>(aTwo.Year) - static_cast<sal_Int32>(aOne.Year);
907 if ( !nTmp ) {
908 nTmp = static_cast<sal_Int32>(aTwo.Month) - static_cast<sal_Int32>(aOne.Month);
909 if ( !nTmp )
910 nTmp = static_cast<sal_Int32>(aTwo.Day) - static_cast<sal_Int32>(aOne.Day);
913 if ( nTmp < 0 )
914 nCompare = -1;
915 else if ( nTmp == 0 )
916 nCompare = 0;
917 else
918 nCompare = 1;
920 break;
922 case DataType::TIME :
924 Time aOne, aTwo;
925 sal_Int32 nTmp;
927 if ( xResultOne->absolute( nIndexOne ) )
928 aOne = xRowOne->getTime( nColumn );
929 if ( xResultTwo->absolute( nIndexTwo ) )
930 aTwo = xRowTwo->getTime( nColumn );
932 nTmp = static_cast<sal_Int32>(aTwo.Hours) - static_cast<sal_Int32>(aOne.Hours);
933 if ( !nTmp )
934 nTmp = static_cast<sal_Int32>(aTwo.Minutes) - static_cast<sal_Int32>(aOne.Minutes);
935 if ( !nTmp )
936 nTmp = static_cast<sal_Int32>(aTwo.Seconds) - static_cast<sal_Int32>(aOne.Seconds);
937 if ( !nTmp )
938 nTmp = static_cast<sal_Int32>(aTwo.NanoSeconds)
939 - static_cast<sal_Int32>(aOne.NanoSeconds);
941 if ( nTmp < 0 )
942 nCompare = -1;
943 else if ( nTmp == 0 )
944 nCompare = 0;
945 else
946 nCompare = 1;
948 break;
950 case DataType::TIMESTAMP :
952 DateTime aOne, aTwo;
953 sal_Int32 nTmp;
955 if ( xResultOne->absolute( nIndexOne ) )
956 aOne = xRowOne->getTimestamp( nColumn );
957 if ( xResultTwo->absolute( nIndexTwo ) )
958 aTwo = xRowTwo->getTimestamp( nColumn );
960 nTmp = static_cast<sal_Int32>(aTwo.Year) - static_cast<sal_Int32>(aOne.Year);
961 if ( !nTmp )
962 nTmp = static_cast<sal_Int32>(aTwo.Month) - static_cast<sal_Int32>(aOne.Month);
963 if ( !nTmp )
964 nTmp = static_cast<sal_Int32>(aTwo.Day) - static_cast<sal_Int32>(aOne.Day);
965 if ( !nTmp )
966 nTmp = static_cast<sal_Int32>(aTwo.Hours) - static_cast<sal_Int32>(aOne.Hours);
967 if ( !nTmp )
968 nTmp = static_cast<sal_Int32>(aTwo.Minutes) - static_cast<sal_Int32>(aOne.Minutes);
969 if ( !nTmp )
970 nTmp = static_cast<sal_Int32>(aTwo.Seconds) - static_cast<sal_Int32>(aOne.Seconds);
971 if ( !nTmp )
972 nTmp = static_cast<sal_Int32>(aTwo.NanoSeconds)
973 - static_cast<sal_Int32>(aOne.NanoSeconds);
975 if ( nTmp < 0 )
976 nCompare = -1;
977 else if ( nTmp == 0 )
978 nCompare = 0;
979 else
980 nCompare = 1;
982 break;
984 case DataType::REAL :
986 float aOne = 0;
987 float aTwo = 0;
989 if ( xResultOne->absolute( nIndexOne ) )
990 aOne = xRowOne->getFloat( nColumn );
991 if ( xResultTwo->absolute( nIndexTwo ) )
992 aTwo = xRowTwo->getFloat( nColumn );
994 if ( aOne < aTwo )
995 nCompare = -1;
996 else if ( aOne == aTwo )
997 nCompare = 0;
998 else
999 nCompare = 1;
1001 break;
1003 case DataType::FLOAT :
1004 case DataType::DOUBLE :
1006 double aOne = 0;
1007 double aTwo = 0;
1009 if ( xResultOne->absolute( nIndexOne ) )
1010 aOne = xRowOne->getDouble( nColumn );
1011 if ( xResultTwo->absolute( nIndexTwo ) )
1012 aTwo = xRowTwo->getDouble( nColumn );
1014 if ( aOne < aTwo )
1015 nCompare = -1;
1016 else if ( aOne == aTwo )
1017 nCompare = 0;
1018 else
1019 nCompare = 1;
1021 break;
1023 default:
1025 OSL_FAIL( "DataType not supported for compare!" );
1029 return nCompare;
1033 sal_Int32 SortedResultSet::CompareImpl( const Reference < XResultSet >& xResultOne,
1034 const Reference < XResultSet >& xResultTwo,
1035 sal_Int32 nIndexOne, sal_Int32 nIndexTwo )
1037 sal_IntPtr nCompare = 0;
1038 SortInfo* pInfo = mpSortInfo;
1040 while ( !nCompare && pInfo )
1042 if ( pInfo->mbUseOwnCompare )
1044 nCompare = CompareImpl( xResultOne, xResultTwo,
1045 nIndexOne, nIndexTwo, pInfo );
1047 else
1049 Any aOne, aTwo;
1051 Reference < XRow > xRowOne =
1052 Reference< XRow >::query( xResultOne );
1053 Reference < XRow > xRowTwo =
1054 Reference< XRow >::query( xResultTwo );
1056 if ( xResultOne->absolute( nIndexOne ) )
1057 aOne = xRowOne->getObject( pInfo->mnColumn, nullptr );
1058 if ( xResultTwo->absolute( nIndexTwo ) )
1059 aTwo = xRowTwo->getObject( pInfo->mnColumn, nullptr );
1061 nCompare = pInfo->mxCompareFunction->compare( aOne, aTwo );
1064 if ( ! pInfo->mbAscending )
1065 nCompare = - nCompare;
1067 pInfo = pInfo->mpNext;
1070 return nCompare;
1074 sal_Int32 SortedResultSet::Compare( SortListData const *pOne,
1075 SortListData const *pTwo )
1077 sal_IntPtr nIndexOne;
1078 sal_IntPtr nIndexTwo;
1080 Reference < XResultSet > xResultOne;
1081 Reference < XResultSet > xResultTwo;
1083 if ( pOne->mbModified )
1085 xResultOne = mxOther;
1086 nIndexOne = pOne->mnOldPos;
1088 else
1090 xResultOne = mxOriginal;
1091 nIndexOne = pOne->mnCurPos;
1094 if ( pTwo->mbModified )
1096 xResultTwo = mxOther;
1097 nIndexTwo = pTwo->mnOldPos;
1099 else
1101 xResultTwo = mxOriginal;
1102 nIndexTwo = pTwo->mnCurPos;
1105 sal_IntPtr nCompare;
1106 nCompare = CompareImpl( xResultOne, xResultTwo,
1107 nIndexOne, nIndexTwo );
1108 return nCompare;
1112 sal_Int32 SortedResultSet::FindPos( SortListData const *pEntry,
1113 sal_IntPtr _nStart, sal_IntPtr _nEnd )
1115 if ( _nStart > _nEnd )
1116 return _nStart + 1;
1118 sal_IntPtr nStart = _nStart;
1119 sal_IntPtr nEnd = _nEnd;
1120 sal_IntPtr nMid = 0, nCompare = 0;
1123 while ( nStart <= nEnd )
1125 nMid = ( nEnd - nStart ) / 2 + nStart;
1126 SortListData *pMid = maS2O.GetData( nMid );
1127 nCompare = Compare( pEntry, pMid );
1129 if ( !nCompare )
1130 nCompare = (pEntry != pMid) ? ((pEntry < pMid) ? -1 : 1) : 0;
1132 if ( nCompare < 0 ) // pEntry < pMid
1133 nEnd = nMid - 1;
1134 else
1135 nStart = nMid + 1;
1138 if ( nCompare < 0 ) // pEntry < pMid
1139 return nMid;
1140 else
1141 return nMid+1;
1145 void SortedResultSet::PropertyChanged( const PropertyChangeEvent& rEvt )
1147 std::unique_lock aGuard( maMutex );
1149 if ( !maPropChangeListeners.hasContainedTypes(aGuard) )
1150 return;
1152 // Notify listeners interested especially in the changed property.
1153 OInterfaceContainerHelper4<XPropertyChangeListener>* pPropsContainer =
1154 maPropChangeListeners.getContainer( aGuard, rEvt.PropertyName );
1155 if ( pPropsContainer )
1156 pPropsContainer->notifyEach( aGuard, &XPropertyChangeListener::propertyChange, rEvt );
1158 // Notify listeners interested in all properties.
1159 pPropsContainer = maPropChangeListeners.getContainer( aGuard, OUString() );
1160 if ( pPropsContainer )
1161 pPropsContainer->notifyEach( aGuard, &XPropertyChangeListener::propertyChange, rEvt );
1165 // public methods
1168 void SortedResultSet::CopyData( SortedResultSet *pSource )
1170 const SortedEntryList& rSrcS2O = pSource->maS2O;
1172 sal_IntPtr i, nCount;
1174 maS2O.Clear();
1175 m_O2S.clear();
1176 m_ModList.clear();
1178 maS2O.Insert( nullptr, 0 );
1179 m_O2S.push_back(0);
1181 nCount = rSrcS2O.Count();
1183 for ( i=1; i<nCount; i++ )
1185 maS2O.Insert( std::unique_ptr<SortListData>(new SortListData( rSrcS2O[ i ] )), i );
1186 m_O2S.push_back(pSource->m_O2S[i]);
1189 mnLastSort = maS2O.Count();
1190 mxOther = pSource->mxOriginal;
1192 if ( !mpSortInfo )
1194 mpSortInfo = pSource->mpSortInfo;
1195 mbIsCopy = true;
1200 void SortedResultSet::Initialize(
1201 const Sequence < NumberedSortingInfo > &xSortInfo,
1202 const Reference< XAnyCompareFactory > &xCompFactory )
1204 BuildSortInfo( mxOriginal, xSortInfo, xCompFactory );
1205 // Insert dummy at pos 0
1206 maS2O.Insert( std::unique_ptr<SortListData>(new SortListData( 0 )), 0 );
1208 sal_IntPtr nIndex = 1;
1210 // now fetch all the elements from the original result set,
1211 // get there new position in the sorted result set and insert
1212 // an entry in the sorted to original mapping list
1213 try {
1214 while ( mxOriginal->absolute( nIndex ) )
1216 std::unique_ptr<SortListData> pData(new SortListData( nIndex ));
1217 sal_IntPtr nPos = FindPos( pData.get(), 1, nIndex-1 );
1219 maS2O.Insert( std::move(pData), nPos );
1221 nIndex++;
1224 catch (const SQLException&)
1226 TOOLS_WARN_EXCEPTION("ucb", "");
1229 // when we have fetched all the elements, we can create the
1230 // original to sorted mapping list from the s2o list
1231 m_O2S.clear();
1232 m_O2S.push_back(0);
1234 // insert some dummy entries first and replace then
1235 // the entries with the right ones
1236 size_t i;
1238 for ( i=1; i<maS2O.Count(); i++ )
1239 m_O2S.push_back(0);
1240 for ( i=1; i<maS2O.Count(); i++ )
1241 m_O2S[maS2O[i]] = i;
1243 mnCount = maS2O.Count() - 1;
1247 void SortedResultSet::CheckProperties( sal_Int32 nOldCount, bool bWasFinal )
1249 std::unique_lock aGuard( maMutex );
1251 if ( !maPropChangeListeners.hasContainedTypes(aGuard) )
1252 return;
1254 try {
1255 // check for propertyChangeEvents
1256 if ( nOldCount != GetCount() )
1258 bool bIsFinal = false;
1259 PropertyChangeEvent aEvt;
1261 aEvt.PropertyName = "RowCount";
1262 aEvt.Further = false;
1263 aEvt.PropertyHandle = -1;
1264 aEvt.OldValue <<= nOldCount;
1265 aEvt.NewValue <<= GetCount();
1267 PropertyChanged( aEvt );
1269 OUString aName = "IsRowCountFinal";
1270 Any aRet = getPropertyValue( aName );
1271 if ( (aRet >>= bIsFinal) && bIsFinal != bWasFinal )
1273 aEvt.PropertyName = aName;
1274 aEvt.Further = false;
1275 aEvt.PropertyHandle = -1;
1276 aEvt.OldValue <<= bWasFinal;
1277 aEvt.NewValue <<= bIsFinal;
1278 PropertyChanged( aEvt );
1282 catch (const UnknownPropertyException&) {}
1283 catch (const WrappedTargetException&) {}
1287 void SortedResultSet::InsertNew( sal_Int32 nPos, sal_Int32 nCount )
1289 // for all entries in the msS20-list, which are >= nPos, increase by nCount
1290 sal_IntPtr i, nEnd;
1292 nEnd = maS2O.Count();
1293 for ( i=1; i<=nEnd; i++ )
1295 SortListData *pData = maS2O.GetData( i );
1296 if ( pData->mnCurPos >= nPos )
1298 pData->mnCurPos += nCount;
1302 // and append the new entries at the end of the maS2O-list or insert at the
1303 // position nPos in the maS2O-list
1304 for ( i=0; i<nCount; i++ )
1306 nEnd += 1;
1307 std::unique_ptr<SortListData> pData(new SortListData( nEnd ));
1309 maS2O.Insert( std::move(pData), nEnd ); // Insert( Value, Position )
1310 m_O2S.insert(m_O2S.begin() + nPos + i, nEnd);
1313 mnCount += nCount;
1317 void SortedResultSet::Remove( sal_Int32 nPos, sal_Int32 nCount, EventList *pEvents )
1319 sal_IntPtr nOldLastSort;
1321 // correct mnLastSort first
1322 nOldLastSort = mnLastSort;
1323 if ( nPos <= mnLastSort )
1325 if ( nPos + nCount - 1 <= mnLastSort )
1326 mnLastSort -= nCount;
1327 else
1328 mnLastSort = nPos - 1;
1331 // remove the entries from the lists and correct the positions
1332 // in the original2sorted list
1333 for ( sal_IntPtr i=0; i < nCount; i++ )
1335 sal_IntPtr nSortPos = m_O2S[nPos];
1336 m_O2S.erase(m_O2S.begin() + nPos);
1338 for (size_t j=1; j < m_O2S.size(); ++j)
1340 sal_IntPtr nVal = m_O2S[j];
1341 if ( nVal > nSortPos )
1343 --nVal;
1344 m_O2S[j] = nVal;
1348 std::unique_ptr<SortListData> pData = maS2O.Remove( nSortPos );
1349 if ( pData->mbModified )
1350 m_ModList.erase(std::find(m_ModList.begin(), m_ModList.end(), pData.get()));
1352 // generate remove Event, but not for new entries
1353 if ( nSortPos <= nOldLastSort )
1354 pEvents->AddEvent( ListActionType::REMOVED, nSortPos );
1357 // correct the positions in the sorted list
1358 for ( sal_uInt32 i=1; i<= maS2O.Count(); i++ )
1360 SortListData *pData = maS2O.GetData( i );
1361 if ( pData->mnCurPos > nPos )
1362 pData->mnCurPos -= nCount;
1365 mnCount -= nCount;
1369 void SortedResultSet::Move( sal_Int32 nPos, sal_Int32 nCount, sal_Int32 nOffset )
1371 if ( !nOffset )
1372 return;
1374 sal_IntPtr i, nSortPos, nTo;
1375 SortListData *pData;
1377 for ( i=0; i<nCount; i++ )
1379 nSortPos = m_O2S[nPos + i];
1380 pData = maS2O.GetData( nSortPos );
1381 pData->mnCurPos += nOffset;
1384 if ( nOffset < 0 )
1386 for ( i=nPos+nOffset; i<nPos; i++ )
1388 nSortPos = m_O2S[i];
1389 pData = maS2O.GetData( nSortPos );
1390 pData->mnCurPos += nCount;
1393 else
1395 sal_IntPtr nStart = nPos + nCount;
1396 sal_IntPtr nEnd = nStart + nOffset;
1397 for ( i=nStart; i<nEnd; i++ )
1399 nSortPos = m_O2S[i];
1400 pData = maS2O.GetData( nSortPos );
1401 pData->mnCurPos -= nCount;
1405 // remember the to be moved entries
1406 std::unique_ptr<sal_IntPtr[]> pTmpArr(new sal_IntPtr[ nCount ]);
1407 for ( i=0; i<nCount; i++ )
1408 pTmpArr[i] = m_O2S[nPos + i];
1410 // now move the entries, which are in the way
1411 if ( nOffset < 0 )
1413 // be carefully here, because nOffset is negative here, so an
1414 // addition is a subtraction
1415 sal_IntPtr nFrom = nPos - 1;
1416 nTo = nPos + nCount - 1;
1418 // same for i here
1419 for ( i=0; i>nOffset; i-- )
1421 sal_IntPtr const nVal = m_O2S[nFrom + i];
1422 m_O2S[nTo + i] = nVal;
1426 else
1428 sal_IntPtr nStart = nPos + nCount;
1429 for ( i=0; i<nOffset; i++ )
1431 sal_IntPtr const nVal = m_O2S[nStart + i];
1432 m_O2S[nPos + i] = nVal;
1436 // finally put the remembered entries at their new location
1437 nTo = nPos + nOffset;
1438 for ( i=0; i<nCount; i++ )
1440 m_O2S[nTo + i] = pTmpArr[i];
1445 void SortedResultSet::BuildSortInfo(
1446 const Reference< XResultSet >& aResult,
1447 const Sequence < NumberedSortingInfo > &xSortInfo,
1448 const Reference< XAnyCompareFactory > &xCompFactory )
1450 Reference < XResultSetMetaDataSupplier > xMeta ( aResult, UNO_QUERY );
1452 if ( ! xMeta.is() )
1454 OSL_FAIL( "No MetaData, No Sorting!" );
1455 return;
1458 Reference < XResultSetMetaData > xData = xMeta->getMetaData();
1459 const NumberedSortingInfo *pSortInfo = xSortInfo.getConstArray();
1461 sal_Int32 nColumn;
1462 OUString aPropName;
1463 SortInfo *pInfo;
1465 for ( sal_Int32 i=xSortInfo.getLength(); i > 0; )
1467 --i;
1468 nColumn = pSortInfo[ i ].ColumnIndex;
1469 aPropName = xData->getColumnName( nColumn );
1470 pInfo = new SortInfo;
1472 if ( xCompFactory.is() )
1473 pInfo->mxCompareFunction = xCompFactory->createAnyCompareByName(
1474 aPropName );
1476 if ( pInfo->mxCompareFunction.is() )
1478 pInfo->mbUseOwnCompare = false;
1479 pInfo->mnType = 0;
1481 else
1483 pInfo->mbUseOwnCompare = true;
1484 pInfo->mnType = xData->getColumnType( nColumn );
1487 pInfo->mnColumn = nColumn;
1488 pInfo->mbAscending = pSortInfo[ i ].Ascending;
1489 pInfo->mbCaseSensitive = xData->isCaseSensitive( nColumn );
1490 pInfo->mpNext = mpSortInfo;
1491 mpSortInfo = pInfo;
1496 void SortedResultSet::SetChanged( sal_Int32 nPos, sal_Int32 nCount )
1498 for ( sal_IntPtr i=0; i<nCount; i++ )
1500 sal_IntPtr const nSortPos = m_O2S[nPos];
1501 if ( nSortPos < mnLastSort )
1503 SortListData *pData = maS2O.GetData( nSortPos );
1504 if ( ! pData->mbModified )
1506 pData->mbModified = true;
1507 m_ModList.push_back(pData);
1510 nPos += 1;
1515 void SortedResultSet::ResortModified( EventList* pList )
1517 sal_IntPtr nCompare, nCurPos, nNewPos;
1518 sal_IntPtr nStart, nEnd, nOffset, nVal;
1520 try {
1521 for (size_t i = 0; i < m_ModList.size(); ++i)
1523 SortListData *const pData = m_ModList[i];
1524 nCompare = CompareImpl( mxOther, mxOriginal,
1525 pData->mnOldPos, pData->mnCurPos );
1526 pData->mbModified = false;
1527 if ( nCompare != 0 )
1529 nCurPos = m_O2S[pData->mnCurPos];
1530 if ( nCompare < 0 )
1532 nNewPos = FindPos( pData, 1, nCurPos-1 );
1533 nStart = nNewPos;
1534 nEnd = nCurPos;
1535 nOffset = 1;
1537 else
1539 nNewPos = FindPos( pData, nCurPos+1, mnLastSort );
1540 nStart = nCurPos;
1541 nEnd = mnLastSort;
1542 nOffset = -1;
1545 if ( nNewPos != nCurPos )
1547 // correct the lists!
1548 maS2O.Move( static_cast<sal_uInt32>(nCurPos), nNewPos );
1549 for (size_t j = 1; j < m_O2S.size(); ++j)
1551 nVal = m_O2S[j];
1552 if ( ( nStart <= nVal ) && ( nVal <= nEnd ) )
1554 nVal += nOffset;
1555 m_O2S[j] = nVal;
1559 m_O2S[pData->mnCurPos] = nNewPos;
1561 ListAction aAction;
1562 aAction.Position = nCurPos;
1563 aAction.Count = 1;
1564 aAction.ListActionType = ListActionType::MOVED;
1565 aAction.ActionInfo <<= nNewPos-nCurPos;
1566 pList->Insert( aAction );
1568 pList->AddEvent( ListActionType::PROPERTIES_CHANGED, nNewPos );
1572 catch (const SQLException&)
1574 TOOLS_WARN_EXCEPTION("ucb", "");
1577 m_ModList.clear();
1581 void SortedResultSet::ResortNew( EventList* pList )
1583 sal_IntPtr i, nNewPos, nVal;
1585 try {
1586 for ( i = mnLastSort; i<static_cast<sal_IntPtr>(maS2O.Count()); i++ )
1588 SortListData *const pData = m_ModList[i];
1589 nNewPos = FindPos( pData, 1, mnLastSort );
1590 if ( nNewPos != i )
1592 maS2O.Move( static_cast<sal_uInt32>(i), nNewPos );
1593 for (size_t j=1; j< m_O2S.size(); ++j)
1595 nVal = m_O2S[j];
1596 if ( nVal >= nNewPos )
1597 m_O2S[j] = nVal + 1;
1599 m_O2S[pData->mnCurPos] = nNewPos;
1601 mnLastSort++;
1602 pList->AddEvent( ListActionType::INSERTED, nNewPos );
1605 catch (const SQLException&)
1607 TOOLS_WARN_EXCEPTION("ucb", "");
1612 // SortListData
1615 SortListData::SortListData( sal_IntPtr nPos )
1616 : mbModified(false)
1617 , mnCurPos(nPos)
1618 , mnOldPos(nPos)
1622 SortedEntryList::SortedEntryList()
1626 SortedEntryList::~SortedEntryList()
1630 void SortedEntryList::Clear()
1632 maData.clear();
1636 void SortedEntryList::Insert( std::unique_ptr<SortListData> pEntry, sal_Int32 nPos )
1638 if ( nPos < static_cast<sal_IntPtr>(maData.size()) )
1639 maData.insert( maData.begin() + nPos, std::move(pEntry) );
1640 else
1641 maData.push_back( std::move(pEntry) );
1644 void SortedEntryList::Move( sal_Int32 nOldPos, sal_Int32 nNewPos )
1646 auto p = std::move(maData[nOldPos]);
1647 maData.erase( maData.begin() + nOldPos );
1648 maData.insert(maData.begin() + nNewPos, std::move(p));
1651 std::unique_ptr<SortListData> SortedEntryList::Remove( sal_Int32 nPos )
1653 std::unique_ptr<SortListData> pData;
1655 if ( nPos < static_cast<sal_IntPtr>(maData.size()) )
1657 pData = std::move(maData[ nPos ]);
1658 maData.erase( maData.begin() + nPos );
1661 return pData;
1665 SortListData* SortedEntryList::GetData( sal_Int32 nPos )
1667 SortListData *pData;
1669 if ( nPos < static_cast<sal_IntPtr>(maData.size()) )
1670 pData = maData[ nPos ].get();
1671 else
1672 pData = nullptr;
1674 return pData;
1678 sal_Int32 SortedEntryList::operator [] ( sal_Int32 nPos ) const
1680 SortListData *pData;
1682 if ( nPos < static_cast<sal_IntPtr>(maData.size()) )
1683 pData = maData[ nPos ].get();
1684 else
1685 pData = nullptr;
1687 if ( pData )
1688 if ( ! pData->mbModified )
1689 return pData->mnCurPos;
1690 else
1692 OSL_FAIL( "SortedEntryList: Can't get value for modified entry!");
1693 return 0;
1695 else
1697 OSL_FAIL( "SortedEntryList: invalid pos!");
1698 return 0;
1703 SRSPropertySetInfo::SRSPropertySetInfo()
1705 maProps[0].Name = "RowCount";
1706 maProps[0].Handle = -1;
1707 maProps[0].Type = cppu::UnoType<OUString>::get();
1708 maProps[0].Attributes = -1;
1710 maProps[1].Name = "IsRowCountFinal";
1711 maProps[1].Handle = -1;
1712 maProps[1].Type = cppu::UnoType<bool>::get();
1713 maProps[1].Attributes = -1;
1716 // XPropertySetInfo methods.
1718 Sequence< Property > SAL_CALL
1719 SRSPropertySetInfo::getProperties()
1721 return Sequence < Property > ( maProps, 2 );
1725 Property SAL_CALL
1726 SRSPropertySetInfo::getPropertyByName( const OUString& Name )
1728 if ( Name == "RowCount" )
1729 return maProps[0];
1730 else if ( Name == "IsRowCountFinal" )
1731 return maProps[1];
1732 else
1733 throw UnknownPropertyException(Name);
1737 sal_Bool SAL_CALL
1738 SRSPropertySetInfo::hasPropertyByName( const OUString& Name )
1740 if ( Name == "RowCount" )
1741 return true;
1742 else if ( Name == "IsRowCountFinal" )
1743 return true;
1744 else
1745 return false;
1748 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */