merged tag ooo/DEV300_m83
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blobe5c8794483382b578a53d9bd0c67156586436388
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucb.hxx"
31 #include <cachedcontentresultset.hxx>
32 #include <com/sun/star/sdbc/FetchDirection.hpp>
33 #include <com/sun/star/ucb/FetchError.hpp>
34 #include <com/sun/star/ucb/ResultSetException.hpp>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/script/XTypeConverter.hpp>
37 #include <com/sun/star/sdbc/ResultSetType.hpp>
38 #include <rtl/ustring.hxx>
39 #include <osl/diagnose.h>
41 using namespace com::sun::star::beans;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star::script;
44 using namespace com::sun::star::sdbc;
45 using namespace com::sun::star::ucb;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::util;
48 using namespace cppu;
49 using namespace rtl;
51 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
52 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
54 //--------------------------------------------------------------------------
55 //--------------------------------------------------------------------------
56 //define for getXXX methods of interface XRow
57 //--------------------------------------------------------------------------
58 //--------------------------------------------------------------------------
60 //if you change this macro please pay attention to
61 //function ::getObject, where this is similar implemented
63 #define XROW_GETXXX( getXXX, Type ) \
64 impl_EnsureNotDisposed(); \
65 ReacquireableGuard aGuard( m_aMutex ); \
66 sal_Int32 nRow = m_nRow; \
67 sal_Int32 nFetchSize = m_nFetchSize; \
68 sal_Int32 nFetchDirection = m_nFetchDirection; \
69 if( !m_aCache.hasRow( nRow ) ) \
70 { \
71 if( !m_aCache.hasCausedException( nRow ) ) \
72 { \
73 if( !m_xFetchProvider.is() ) \
74 { \
75 OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \
76 throw SQLException(); \
77 } \
78 aGuard.clear(); \
79 if( impl_isForwardOnly() ) \
80 applyPositionToOrigin( nRow ); \
82 impl_fetchData( nRow, nFetchSize, nFetchDirection ); \
83 } \
84 aGuard.reacquire(); \
85 if( !m_aCache.hasRow( nRow ) ) \
86 { \
87 m_bLastReadWasFromCache = sal_False; \
88 aGuard.clear(); \
89 applyPositionToOrigin( nRow ); \
90 impl_init_xRowOrigin(); \
91 return m_xRowOrigin->getXXX( columnIndex ); \
92 } \
93 } \
94 const Any& rValue = m_aCache.getAny( nRow, columnIndex );\
95 Type aRet = Type(); \
96 m_bLastReadWasFromCache = sal_True; \
97 m_bLastCachedReadWasNull = !( rValue >>= aRet ); \
98 /* Last chance. Try type converter service... */ \
99 if ( m_bLastCachedReadWasNull && rValue.hasValue() ) \
101 Reference< XTypeConverter > xConverter \
102 = getTypeConverter(); \
103 if ( xConverter.is() ) \
105 try \
107 Any aConvAny = xConverter->convertTo( \
108 rValue, \
109 getCppuType( static_cast< \
110 const Type * >( 0 ) ) ); \
111 m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \
113 catch ( IllegalArgumentException ) \
116 catch ( CannotConvertException ) \
121 return aRet;
123 //--------------------------------------------------------------------------
124 //--------------------------------------------------------------------------
125 // CCRS_Cache methoeds.
126 //--------------------------------------------------------------------------
127 //--------------------------------------------------------------------------
129 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
130 const Reference< XContentIdentifierMapping > & xMapping )
131 : m_pResult( NULL )
132 , m_xContentIdentifierMapping( xMapping )
133 , m_pMappedReminder( NULL )
137 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
139 delete m_pResult;
142 void SAL_CALL CachedContentResultSet::CCRS_Cache
143 ::clear()
145 if( m_pResult )
147 delete m_pResult;
148 m_pResult = NULL;
150 clearMappedReminder();
153 void SAL_CALL CachedContentResultSet::CCRS_Cache
154 ::loadData( const FetchResult& rResult )
156 clear();
157 m_pResult = new FetchResult( rResult );
160 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
161 ::hasRow( sal_Int32 row )
163 if( !m_pResult )
164 return sal_False;
165 long nStart = m_pResult->StartIndex;
166 long nEnd = nStart;
167 if( m_pResult->Orientation )
168 nEnd += m_pResult->Rows.getLength() - 1;
169 else
170 nStart -= m_pResult->Rows.getLength() + 1;
172 return nStart <= row && row <= nEnd;
175 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
176 ::getMaxRow()
178 if( !m_pResult )
179 return 0;
180 long nEnd = m_pResult->StartIndex;
181 if( m_pResult->Orientation )
182 return nEnd += m_pResult->Rows.getLength() - 1;
183 else
184 return nEnd;
187 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
188 ::hasKnownLast()
190 if( !m_pResult )
191 return sal_False;
193 if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
194 && m_pResult->Orientation
195 && m_pResult->Rows.getLength() )
196 return sal_True;
198 return sal_False;
201 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
202 ::hasCausedException( sal_Int32 nRow )
204 if( !m_pResult )
205 return sal_False;
206 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
207 return sal_False;
209 long nEnd = m_pResult->StartIndex;
210 if( m_pResult->Orientation )
211 nEnd += m_pResult->Rows.getLength();
213 return nRow == nEnd+1;
216 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
217 ::getRowAny( sal_Int32 nRow )
218 throw( SQLException,
219 RuntimeException )
221 if( !nRow )
222 throw SQLException();
223 if( !m_pResult )
224 throw SQLException();
225 if( !hasRow( nRow ) )
226 throw SQLException();
228 long nDiff = nRow - m_pResult->StartIndex;
229 if( nDiff < 0 )
230 nDiff *= -1;
232 return (m_pResult->Rows)[nDiff];
235 void SAL_CALL CachedContentResultSet::CCRS_Cache
236 ::remindMapped( sal_Int32 nRow )
238 //remind that this row was mapped
239 if( !m_pResult )
240 return;
241 long nDiff = nRow - m_pResult->StartIndex;
242 if( nDiff < 0 )
243 nDiff *= -1;
244 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
245 if( nDiff < pMappedReminder->getLength() )
246 (*pMappedReminder)[nDiff] = sal_True;
249 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
250 ::isRowMapped( sal_Int32 nRow )
252 if( !m_pMappedReminder || !m_pResult )
253 return sal_False;
254 long nDiff = nRow - m_pResult->StartIndex;
255 if( nDiff < 0 )
256 nDiff *= -1;
257 if( nDiff < m_pMappedReminder->getLength() )
258 return (*m_pMappedReminder)[nDiff];
259 return sal_False;
262 void SAL_CALL CachedContentResultSet::CCRS_Cache
263 ::clearMappedReminder()
265 delete m_pMappedReminder;
266 m_pMappedReminder = NULL;
269 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
270 ::getMappedReminder()
272 if( !m_pMappedReminder )
274 sal_Int32 nCount = m_pResult->Rows.getLength();
275 m_pMappedReminder = new Sequence< sal_Bool >( nCount );
276 for( ;nCount; nCount-- )
277 (*m_pMappedReminder)[nCount] = sal_False;
279 return m_pMappedReminder;
282 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
283 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
284 throw( SQLException,
285 RuntimeException )
287 if( !nColumnIndex )
288 throw SQLException();
289 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
291 Any& rRow = getRowAny( nRow );
292 Sequence< Any > aValue;
293 rRow >>= aValue;
294 if( m_xContentIdentifierMapping->mapRow( aValue ) )
296 rRow <<= aValue;
297 remindMapped( nRow );
299 else
300 m_xContentIdentifierMapping.clear();
302 const Sequence< Any >& rRow =
303 (* reinterpret_cast< const Sequence< Any > * >
304 (getRowAny( nRow ).getValue() ));
306 if( nColumnIndex > rRow.getLength() )
307 throw SQLException();
308 return rRow[nColumnIndex-1];
311 const rtl::OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
312 ::getContentIdentifierString( sal_Int32 nRow )
313 throw( com::sun::star::uno::RuntimeException )
317 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
319 Any& rRow = getRowAny( nRow );
320 rtl::OUString aValue;
321 rRow >>= aValue;
322 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
323 remindMapped( nRow );
325 return (* reinterpret_cast< const rtl::OUString * >
326 (getRowAny( nRow ).getValue() ));
328 catch( SQLException )
330 throw RuntimeException();
334 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
335 ::getContentIdentifier( sal_Int32 nRow )
336 throw( com::sun::star::uno::RuntimeException )
340 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
342 Any& rRow = getRowAny( nRow );
343 Reference< XContentIdentifier > aValue;
344 rRow >>= aValue;
345 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
346 remindMapped( nRow );
348 return (* reinterpret_cast< const Reference< XContentIdentifier > * >
349 (getRowAny( nRow ).getValue() ));
351 catch( SQLException )
353 throw RuntimeException();
357 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
358 ::getContent( sal_Int32 nRow )
359 throw( com::sun::star::uno::RuntimeException )
363 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
365 Any& rRow = getRowAny( nRow );
366 Reference< XContent > aValue;
367 rRow >>= aValue;
368 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
369 remindMapped( nRow );
371 return (* reinterpret_cast< const Reference< XContent > * >
372 (getRowAny( nRow ).getValue() ));
374 catch( SQLException )
376 throw RuntimeException();
380 //--------------------------------------------------------------------------
381 //--------------------------------------------------------------------------
382 // class CCRS_PropertySetInfo
383 //--------------------------------------------------------------------------
384 //--------------------------------------------------------------------------
386 class CCRS_PropertySetInfo :
387 public cppu::OWeakObject,
388 public com::sun::star::lang::XTypeProvider,
389 public com::sun::star::beans::XPropertySetInfo
391 friend class CachedContentResultSet;
393 //my Properties
394 Sequence< com::sun::star::beans::Property >*
395 m_pProperties;
397 //some helping variables ( names for my special properties )
398 static rtl::OUString m_aPropertyNameForCount;
399 static rtl::OUString m_aPropertyNameForFinalCount;
400 static rtl::OUString m_aPropertyNameForFetchSize;
401 static rtl::OUString m_aPropertyNameForFetchDirection;
403 long m_nFetchSizePropertyHandle;
404 long m_nFetchDirectionPropertyHandle;
406 private:
407 sal_Int32 SAL_CALL
408 impl_getRemainedHandle() const;
410 sal_Bool SAL_CALL
411 impl_queryProperty(
412 const rtl::OUString& rName
413 , com::sun::star::beans::Property& rProp ) const;
414 sal_Int32 SAL_CALL
415 impl_getPos( const rtl::OUString& rName ) const;
417 static sal_Bool SAL_CALL
418 impl_isMyPropertyName( const rtl::OUString& rName );
420 public:
421 CCRS_PropertySetInfo( Reference<
422 XPropertySetInfo > xPropertySetInfoOrigin );
424 virtual ~CCRS_PropertySetInfo();
426 // XInterface
427 XINTERFACE_DECL()
429 // XTypeProvider
430 XTYPEPROVIDER_DECL()
432 // XPropertySetInfo
433 virtual Sequence< com::sun::star::beans::Property > SAL_CALL
434 getProperties()
435 throw( RuntimeException );
437 virtual com::sun::star::beans::Property SAL_CALL
438 getPropertyByName( const rtl::OUString& aName )
439 throw( com::sun::star::beans::UnknownPropertyException, RuntimeException );
441 virtual sal_Bool SAL_CALL
442 hasPropertyByName( const rtl::OUString& Name )
443 throw( RuntimeException );
446 OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( OUString::createFromAscii( "RowCount" ) );
447 OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( OUString::createFromAscii( "IsRowCountFinal" ) );
448 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) );
449 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) );
451 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
452 Reference< XPropertySetInfo > xInfo )
453 : m_pProperties( NULL )
454 , m_nFetchSizePropertyHandle( -1 )
455 , m_nFetchDirectionPropertyHandle( -1 )
457 //initialize list of properties:
459 // it is required, that the received xInfo contains the two
460 // properties with names 'm_aPropertyNameForCount' and
461 // 'm_aPropertyNameForFinalCount'
463 if( xInfo.is() )
465 Sequence<Property> aProps = xInfo->getProperties();
466 m_pProperties = new Sequence<Property> ( aProps );
468 else
470 OSL_ENSURE( sal_False, "The received XPropertySetInfo doesn't contain required properties" );
471 m_pProperties = new Sequence<Property>;
474 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
475 sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
476 sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
477 sal_Int32 nDeleted = 0;
478 if( nFetchSize != -1 )
479 nDeleted++;
480 if( nFetchDirection != -1 )
481 nDeleted++;
483 Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
484 sal_Int32 nOrigProps = pOrigProps->getLength();
486 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
487 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
489 if( n == nFetchSize || n == nFetchDirection )
490 m--;
491 else
492 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
495 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
496 rMyProp.Name = m_aPropertyNameForFetchSize;
497 rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) );
498 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
500 if( nFetchSize != -1 )
501 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
502 else
503 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
505 rMyProp.Handle = m_nFetchSizePropertyHandle;
509 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
510 rMyProp.Name = m_aPropertyNameForFetchDirection;
511 rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) );
512 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
514 if( nFetchSize != -1 )
515 m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
516 else
517 m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
519 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
521 delete pOrigProps;
524 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
526 delete m_pProperties;
529 //--------------------------------------------------------------------------
530 // XInterface methods.
531 //--------------------------------------------------------------------------
532 //list all interfaces inclusive baseclasses of interfaces
533 XINTERFACE_IMPL_2( CCRS_PropertySetInfo
534 , XTypeProvider
535 , XPropertySetInfo
538 //--------------------------------------------------------------------------
539 // XTypeProvider methods.
540 //--------------------------------------------------------------------------
541 //list all interfaces exclusive baseclasses
542 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
543 , XTypeProvider
544 , XPropertySetInfo
546 //--------------------------------------------------------------------------
547 // XPropertySetInfo methods.
548 //--------------------------------------------------------------------------
549 //virtual
550 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
551 ::getProperties() throw( RuntimeException )
553 return *m_pProperties;
556 //virtual
557 Property SAL_CALL CCRS_PropertySetInfo
558 ::getPropertyByName( const rtl::OUString& aName )
559 throw( UnknownPropertyException, RuntimeException )
561 if ( !aName.getLength() )
562 throw UnknownPropertyException();
564 Property aProp;
565 if ( impl_queryProperty( aName, aProp ) )
566 return aProp;
568 throw UnknownPropertyException();
571 //virtual
572 sal_Bool SAL_CALL CCRS_PropertySetInfo
573 ::hasPropertyByName( const rtl::OUString& Name )
574 throw( RuntimeException )
576 return ( impl_getPos( Name ) != -1 );
579 //--------------------------------------------------------------------------
580 // impl_ methods.
581 //--------------------------------------------------------------------------
583 sal_Int32 SAL_CALL CCRS_PropertySetInfo
584 ::impl_getPos( const OUString& rName ) const
586 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
588 const Property& rMyProp = (*m_pProperties)[nN];
589 if( rMyProp.Name == rName )
590 return nN;
592 return -1;
595 sal_Bool SAL_CALL CCRS_PropertySetInfo
596 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
598 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
600 const Property& rMyProp = (*m_pProperties)[nN];
601 if( rMyProp.Name == rName )
603 rProp.Name = rMyProp.Name;
604 rProp.Handle = rMyProp.Handle;
605 rProp.Type = rMyProp.Type;
606 rProp.Attributes = rMyProp.Attributes;
608 return sal_True;
611 return sal_False;
614 //static
615 sal_Bool SAL_CALL CCRS_PropertySetInfo
616 ::impl_isMyPropertyName( const OUString& rPropertyName )
618 return ( rPropertyName == m_aPropertyNameForCount
619 || rPropertyName == m_aPropertyNameForFinalCount
620 || rPropertyName == m_aPropertyNameForFetchSize
621 || rPropertyName == m_aPropertyNameForFetchDirection );
624 sal_Int32 SAL_CALL CCRS_PropertySetInfo
625 ::impl_getRemainedHandle( ) const
627 sal_Int32 nHandle = 1;
629 if( !m_pProperties )
631 OSL_ENSURE( sal_False, "Properties not initialized yet" );
632 return nHandle;
634 sal_Bool bFound = sal_True;
635 while( bFound )
637 bFound = sal_False;
638 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
640 if( nHandle == (*m_pProperties)[nN].Handle )
642 bFound = sal_True;
643 nHandle++;
644 break;
648 return nHandle;
651 //--------------------------------------------------------------------------
652 //--------------------------------------------------------------------------
653 // class CachedContentResultSet
654 //--------------------------------------------------------------------------
655 //--------------------------------------------------------------------------
657 CachedContentResultSet::CachedContentResultSet(
658 const Reference< XMultiServiceFactory > & xSMgr
659 , const Reference< XResultSet > & xOrigin
660 , const Reference< XContentIdentifierMapping > &
661 xContentIdentifierMapping )
662 : ContentResultSetWrapper( xOrigin )
664 , m_xSMgr( xSMgr )
665 , m_xFetchProvider( NULL )
666 , m_xFetchProviderForContentAccess( NULL )
668 , m_xMyPropertySetInfo( NULL )
669 , m_pMyPropSetInfo( NULL )
671 , m_xContentIdentifierMapping( xContentIdentifierMapping )
672 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
673 , m_bAfterLast( sal_False )
674 , m_nLastAppliedPos( 0 )
675 , m_bAfterLastApplied( sal_False )
676 , m_nKnownCount( 0 )
677 , m_bFinalCount( sal_False )
678 , m_nFetchSize(
679 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
680 , m_nFetchDirection(
681 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
683 , m_bLastReadWasFromCache( sal_False )
684 , m_bLastCachedReadWasNull( sal_True )
685 , m_aCache( m_xContentIdentifierMapping )
686 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
687 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
688 , m_aCacheContent( m_xContentIdentifierMapping )
689 , m_bTriedToGetTypeConverter( sal_False )
690 , m_xTypeConverter( NULL )
692 m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
693 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
695 m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
696 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
698 impl_init();
701 CachedContentResultSet::~CachedContentResultSet()
703 impl_deinit();
704 //do not delete m_pMyPropSetInfo, cause it is hold via reference
707 //--------------------------------------------------------------------------
708 // impl_ methods.
709 //--------------------------------------------------------------------------
711 sal_Bool SAL_CALL CachedContentResultSet
712 ::applyPositionToOrigin( sal_Int32 nRow )
713 throw( SQLException,
714 RuntimeException )
716 impl_EnsureNotDisposed();
717 //-------------------------------------------------------------------------
719 @returns
720 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
721 the result set.
724 ReacquireableGuard aGuard( m_aMutex );
725 OSL_ENSURE( nRow >= 0, "only positive values supported" );
726 if( !m_xResultSetOrigin.is() )
728 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
729 return sal_False;
731 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
733 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
734 sal_Bool bAfterLastApplied = m_bAfterLastApplied;
735 sal_Bool bAfterLast = m_bAfterLast;
736 sal_Int32 nForwardOnly = m_nForwardOnly;
738 aGuard.clear();
740 if( bAfterLastApplied || nLastAppliedPos != nRow )
742 if( nForwardOnly == 1 )
744 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
745 throw SQLException();
747 sal_Int32 nN = nRow - nLastAppliedPos;
748 sal_Int32 nM;
749 for( nM = 0; nN--; nM++ )
751 if( !m_xResultSetOrigin->next() )
752 break;
755 aGuard.reacquire();
756 m_nLastAppliedPos += nM;
757 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
758 return nRow == m_nLastAppliedPos;
761 if( !nRow ) //absolute( 0 ) will throw exception
763 m_xResultSetOrigin->beforeFirst();
765 aGuard.reacquire();
766 m_nLastAppliedPos = 0;
767 m_bAfterLastApplied = sal_False;
768 return sal_False;
772 //move absolute, if !nLastAppliedPos
773 //because move relative would throw exception
774 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
776 sal_Bool bValid = m_xResultSetOrigin->absolute( nRow );
778 aGuard.reacquire();
779 m_nLastAppliedPos = nRow;
780 m_bAfterLastApplied = !bValid;
781 return bValid;
783 else
785 sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
787 aGuard.reacquire();
788 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
789 m_bAfterLastApplied = !bValid;
790 return bValid;
793 catch( SQLException& rEx )
795 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
797 sal_Int32 nN = nRow - nLastAppliedPos;
798 sal_Int32 nM;
799 for( nM = 0; nN--; nM++ )
801 if( !m_xResultSetOrigin->next() )
802 break;
805 aGuard.reacquire();
806 m_nLastAppliedPos += nM;
807 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
809 else
810 throw rEx;
813 return nRow == m_nLastAppliedPos;
815 return sal_True;
818 //--------------------------------------------------------------------------
819 //--------------------------------------------------------------------------
820 //define for fetching data
821 //--------------------------------------------------------------------------
822 //--------------------------------------------------------------------------
824 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
825 sal_Bool bDirection = !!( \
826 nFetchDirection != FetchDirection::REVERSE ); \
827 FetchResult aResult = \
828 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
829 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
830 aCache.loadData( aResult ); \
831 sal_Int32 nMax = aCache.getMaxRow(); \
832 sal_Int32 nCurCount = m_nKnownCount; \
833 sal_Bool bIsFinalCount = aCache.hasKnownLast(); \
834 sal_Bool bCurIsFinalCount = m_bFinalCount; \
835 aGuard2.clear(); \
836 if( nMax > nCurCount ) \
837 impl_changeRowCount( nCurCount, nMax ); \
838 if( bIsFinalCount && !bCurIsFinalCount ) \
839 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
841 void SAL_CALL CachedContentResultSet
842 ::impl_fetchData( sal_Int32 nRow
843 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
844 throw( com::sun::star::uno::RuntimeException )
846 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
849 void SAL_CALL CachedContentResultSet
850 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
852 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
853 if( nNew <= nOld )
854 return;
856 //create PropertyChangeEvent and set value
857 PropertyChangeEvent aEvt;
859 osl::Guard< osl::Mutex > aGuard( m_aMutex );
860 aEvt.Source = static_cast< XPropertySet * >( this );
861 aEvt.Further = sal_False;
862 aEvt.OldValue <<= nOld;
863 aEvt.NewValue <<= nNew;
865 m_nKnownCount = nNew;
868 //send PropertyChangeEvent to listeners
869 impl_notifyPropertyChangeListeners( aEvt );
872 void SAL_CALL CachedContentResultSet
873 ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew )
875 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
876 if( ! (!bOld && bNew ) )
877 return;
879 //create PropertyChangeEvent and set value
880 PropertyChangeEvent aEvt;
882 osl::Guard< osl::Mutex > aGuard( m_aMutex );
883 aEvt.Source = static_cast< XPropertySet * >( this );
884 aEvt.Further = sal_False;
885 aEvt.OldValue <<= bOld;
886 aEvt.NewValue <<= bNew;
888 m_bFinalCount = bNew;
891 //send PropertyChangeEvent to listeners
892 impl_notifyPropertyChangeListeners( aEvt );
895 sal_Bool SAL_CALL CachedContentResultSet
896 ::impl_isKnownValidPosition( sal_Int32 nRow )
898 return m_nKnownCount && nRow
899 && nRow <= m_nKnownCount;
902 sal_Bool SAL_CALL CachedContentResultSet
903 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
905 if( !nRow )
906 return sal_True;
907 if( !m_bFinalCount )
908 return sal_False;
909 return nRow > m_nKnownCount;
913 //virtual
914 void SAL_CALL CachedContentResultSet
915 ::impl_initPropertySetInfo()
917 ContentResultSetWrapper::impl_initPropertySetInfo();
919 osl::Guard< osl::Mutex > aGuard( m_aMutex );
920 if( m_pMyPropSetInfo )
921 return;
922 m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
923 m_xMyPropertySetInfo = m_pMyPropSetInfo;
924 m_xPropertySetInfo = m_xMyPropertySetInfo;
927 //--------------------------------------------------------------------------
928 // XInterface methods. ( inherited )
929 //--------------------------------------------------------------------------
930 XINTERFACE_COMMON_IMPL( CachedContentResultSet )
932 Any SAL_CALL CachedContentResultSet
933 ::queryInterface( const Type& rType )
934 throw ( RuntimeException )
936 //list all interfaces inclusive baseclasses of interfaces
938 Any aRet = ContentResultSetWrapper::queryInterface( rType );
939 if( aRet.hasValue() )
940 return aRet;
942 aRet = cppu::queryInterface( rType,
943 static_cast< XTypeProvider* >( this ),
944 static_cast< XServiceInfo* >( this ) );
946 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
949 //--------------------------------------------------------------------------
950 // XTypeProvider methods.
951 //--------------------------------------------------------------------------
952 //list all interfaces exclusive baseclasses
953 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
954 , XTypeProvider
955 , XServiceInfo
956 , XComponent
957 , XCloseable
958 , XResultSetMetaDataSupplier
959 , XPropertySet
961 , XPropertyChangeListener
962 , XVetoableChangeListener
964 , XContentAccess
966 , XResultSet
967 , XRow );
969 //--------------------------------------------------------------------------
970 // XServiceInfo methods.
971 //--------------------------------------------------------------------------
973 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
974 OUString::createFromAscii(
975 "com.sun.star.comp.ucb.CachedContentResultSet" ),
976 OUString::createFromAscii(
977 CACHED_CONTENT_RESULTSET_SERVICE_NAME ) );
979 //--------------------------------------------------------------------------
980 // XPropertySet methods. ( inherited )
981 //--------------------------------------------------------------------------
983 // virtual
984 void SAL_CALL CachedContentResultSet
985 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
986 throw( UnknownPropertyException,
987 PropertyVetoException,
988 IllegalArgumentException,
989 WrappedTargetException,
990 RuntimeException )
992 impl_EnsureNotDisposed();
994 if( !getPropertySetInfo().is() )
996 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
997 throw UnknownPropertyException();
1000 Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
1001 //throws UnknownPropertyException, if so
1003 if( aProp.Attributes & PropertyAttribute::READONLY )
1005 //It is assumed, that the properties
1006 //'RowCount' and 'IsRowCountFinal' are readonly!
1007 throw IllegalArgumentException();
1009 if( aProp.Name == CCRS_PropertySetInfo
1010 ::m_aPropertyNameForFetchDirection )
1012 //check value
1013 sal_Int32 nNew;
1014 if( !( aValue >>= nNew ) )
1016 throw IllegalArgumentException();
1019 if( nNew == FetchDirection::UNKNOWN )
1021 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1023 else if( !( nNew == FetchDirection::FORWARD
1024 || nNew == FetchDirection::REVERSE ) )
1026 throw IllegalArgumentException();
1029 //create PropertyChangeEvent and set value
1030 PropertyChangeEvent aEvt;
1032 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1033 aEvt.Source = static_cast< XPropertySet * >( this );
1034 aEvt.PropertyName = aPropertyName;
1035 aEvt.Further = sal_False;
1036 aEvt.PropertyHandle = m_pMyPropSetInfo->
1037 m_nFetchDirectionPropertyHandle;
1038 aEvt.OldValue <<= m_nFetchDirection;
1039 aEvt.NewValue <<= nNew;
1041 m_nFetchDirection = nNew;
1044 //send PropertyChangeEvent to listeners
1045 impl_notifyPropertyChangeListeners( aEvt );
1047 else if( aProp.Name == CCRS_PropertySetInfo
1048 ::m_aPropertyNameForFetchSize )
1050 //check value
1051 sal_Int32 nNew;
1052 if( !( aValue >>= nNew ) )
1054 throw IllegalArgumentException();
1057 if( nNew < 0 )
1059 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1062 //create PropertyChangeEvent and set value
1063 PropertyChangeEvent aEvt;
1065 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1066 aEvt.Source = static_cast< XPropertySet * >( this );
1067 aEvt.PropertyName = aPropertyName;
1068 aEvt.Further = sal_False;
1069 aEvt.PropertyHandle = m_pMyPropSetInfo->
1070 m_nFetchSizePropertyHandle;
1071 aEvt.OldValue <<= m_nFetchSize;
1072 aEvt.NewValue <<= nNew;
1074 m_nFetchSize = nNew;
1077 //send PropertyChangeEvent to listeners
1078 impl_notifyPropertyChangeListeners( aEvt );
1080 else
1082 impl_init_xPropertySetOrigin();
1084 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1085 if( !m_xPropertySetOrigin.is() )
1087 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1088 return;
1091 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1095 //--------------------------------------------------------------------------
1096 // virtual
1097 Any SAL_CALL CachedContentResultSet
1098 ::getPropertyValue( const OUString& rPropertyName )
1099 throw( UnknownPropertyException,
1100 WrappedTargetException,
1101 RuntimeException )
1103 impl_EnsureNotDisposed();
1105 if( !getPropertySetInfo().is() )
1107 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1108 throw UnknownPropertyException();
1111 Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1112 //throws UnknownPropertyException, if so
1114 Any aValue;
1115 if( rPropertyName == CCRS_PropertySetInfo
1116 ::m_aPropertyNameForCount )
1118 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1119 aValue <<= m_nKnownCount;
1121 else if( rPropertyName == CCRS_PropertySetInfo
1122 ::m_aPropertyNameForFinalCount )
1124 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1125 aValue <<= m_bFinalCount;
1127 else if( rPropertyName == CCRS_PropertySetInfo
1128 ::m_aPropertyNameForFetchSize )
1130 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1131 aValue <<= m_nFetchSize;
1133 else if( rPropertyName == CCRS_PropertySetInfo
1134 ::m_aPropertyNameForFetchDirection )
1136 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1137 aValue <<= m_nFetchDirection;
1139 else
1141 impl_init_xPropertySetOrigin();
1143 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1144 if( !m_xPropertySetOrigin.is() )
1146 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1147 throw UnknownPropertyException();
1150 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1152 return aValue;
1155 //--------------------------------------------------------------------------
1156 // own methods. ( inherited )
1157 //--------------------------------------------------------------------------
1159 //virtual
1160 void SAL_CALL CachedContentResultSet
1161 ::impl_disposing( const EventObject& rEventObject )
1162 throw( RuntimeException )
1165 impl_EnsureNotDisposed();
1166 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1167 //release all references to the broadcaster:
1168 m_xFetchProvider.clear();
1169 m_xFetchProviderForContentAccess.clear();
1171 ContentResultSetWrapper::impl_disposing( rEventObject );
1174 //virtual
1175 void SAL_CALL CachedContentResultSet
1176 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1177 throw( RuntimeException )
1179 impl_EnsureNotDisposed();
1181 PropertyChangeEvent aEvt( rEvt );
1182 aEvt.Source = static_cast< XPropertySet * >( this );
1183 aEvt.Further = sal_False;
1184 //---------
1186 if( CCRS_PropertySetInfo
1187 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1189 //don't notify foreign events on fetchsize and fetchdirection
1190 if( aEvt.PropertyName == CCRS_PropertySetInfo
1191 ::m_aPropertyNameForFetchSize
1192 || aEvt.PropertyName == CCRS_PropertySetInfo
1193 ::m_aPropertyNameForFetchDirection )
1194 return;
1196 //adjust my props 'RowCount' and 'IsRowCountFinal'
1197 if( aEvt.PropertyName == CCRS_PropertySetInfo
1198 ::m_aPropertyNameForCount )
1199 {//RowCount changed
1201 //check value
1202 sal_Int32 nNew = 0;
1203 if( !( aEvt.NewValue >>= nNew ) )
1205 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1206 return;
1209 impl_changeRowCount( m_nKnownCount, nNew );
1211 else if( aEvt.PropertyName == CCRS_PropertySetInfo
1212 ::m_aPropertyNameForFinalCount )
1213 {//IsRowCountFinal changed
1215 //check value
1216 sal_Bool bNew = sal_False;
1217 if( !( aEvt.NewValue >>= bNew ) )
1219 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1220 return;
1222 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1224 return;
1227 //-----------
1228 impl_notifyPropertyChangeListeners( aEvt );
1232 //virtual
1233 void SAL_CALL CachedContentResultSet
1234 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1235 throw( PropertyVetoException,
1236 RuntimeException )
1238 impl_EnsureNotDisposed();
1240 //don't notify events on my properties, cause they are not vetoable
1241 if( CCRS_PropertySetInfo
1242 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1244 return;
1248 PropertyChangeEvent aEvt( rEvt );
1249 aEvt.Source = static_cast< XPropertySet * >( this );
1250 aEvt.Further = sal_False;
1252 impl_notifyVetoableChangeListeners( aEvt );
1255 //--------------------------------------------------------------------------
1256 // XContentAccess methods. ( inherited ) ( -- position dependent )
1257 //--------------------------------------------------------------------------
1259 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1260 impl_EnsureNotDisposed(); \
1261 ReacquireableGuard aGuard( m_aMutex ); \
1262 sal_Int32 nRow = m_nRow; \
1263 sal_Int32 nFetchSize = m_nFetchSize; \
1264 sal_Int32 nFetchDirection = m_nFetchDirection; \
1265 if( !m_aCache##XXX.hasRow( nRow ) ) \
1267 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1269 if( !m_xFetchProviderForContentAccess.is() ) \
1271 OSL_ENSURE( sal_False, "broadcaster was disposed already" );\
1272 throw RuntimeException(); \
1274 aGuard.clear(); \
1275 if( impl_isForwardOnly() ) \
1276 applyPositionToOrigin( nRow ); \
1278 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1280 aGuard.reacquire(); \
1281 if( !m_aCache##XXX.hasRow( nRow ) ) \
1283 aGuard.clear(); \
1284 applyPositionToOrigin( nRow ); \
1285 TYPE aRet = ContentResultSetWrapper::queryXXX(); \
1286 if( m_xContentIdentifierMapping.is() ) \
1287 return m_xContentIdentifierMapping->map##XXX( aRet );\
1288 return aRet; \
1291 return m_aCache##XXX.get##XXX( nRow );
1293 //--------------------------------------------------------------------------
1294 // virtual
1295 OUString SAL_CALL CachedContentResultSet
1296 ::queryContentIdentifierString()
1297 throw( RuntimeException )
1299 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1302 //--------------------------------------------------------------------------
1303 // virtual
1304 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1305 ::queryContentIdentifier()
1306 throw( RuntimeException )
1308 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1311 //--------------------------------------------------------------------------
1312 // virtual
1313 Reference< XContent > SAL_CALL CachedContentResultSet
1314 ::queryContent()
1315 throw( RuntimeException )
1317 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1320 //-----------------------------------------------------------------
1321 // XResultSet methods. ( inherited )
1322 //-----------------------------------------------------------------
1323 //virtual
1325 sal_Bool SAL_CALL CachedContentResultSet
1326 ::next()
1327 throw( SQLException,
1328 RuntimeException )
1330 impl_EnsureNotDisposed();
1332 ReacquireableGuard aGuard( m_aMutex );
1333 //after last
1334 if( m_bAfterLast )
1335 return sal_False;
1336 //last
1337 aGuard.clear();
1338 if( isLast() )
1340 aGuard.reacquire();
1341 m_nRow++;
1342 m_bAfterLast = sal_True;
1343 return sal_False;
1345 aGuard.reacquire();
1346 //known valid position
1347 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1349 m_nRow++;
1350 return sal_True;
1353 //unknown position
1354 sal_Int32 nRow = m_nRow;
1355 aGuard.clear();
1357 sal_Bool bValid = applyPositionToOrigin( nRow + 1 );
1359 aGuard.reacquire();
1360 m_nRow = nRow + 1;
1361 m_bAfterLast = !bValid;
1362 return bValid;
1365 //virtual
1366 sal_Bool SAL_CALL CachedContentResultSet
1367 ::previous()
1368 throw( SQLException,
1369 RuntimeException )
1371 impl_EnsureNotDisposed();
1373 if( impl_isForwardOnly() )
1374 throw SQLException();
1376 ReacquireableGuard aGuard( m_aMutex );
1377 //before first ?:
1378 if( !m_bAfterLast && !m_nRow )
1379 return sal_False;
1380 //first ?:
1381 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1383 m_nRow--;
1384 m_bAfterLast = sal_False;
1385 return sal_False;
1387 //known valid position ?:
1388 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1390 m_nRow--;
1391 m_bAfterLast = sal_False;
1392 return sal_True;
1394 //unknown position:
1395 sal_Int32 nRow = m_nRow;
1396 aGuard.clear();
1398 sal_Bool bValid = applyPositionToOrigin( nRow - 1 );
1400 aGuard.reacquire();
1401 m_nRow = nRow - 1;
1402 m_bAfterLast = sal_False;
1403 return bValid;
1406 //virtual
1407 sal_Bool SAL_CALL CachedContentResultSet
1408 ::absolute( sal_Int32 row )
1409 throw( SQLException,
1410 RuntimeException )
1412 impl_EnsureNotDisposed();
1414 if( !row )
1415 throw SQLException();
1417 if( impl_isForwardOnly() )
1418 throw SQLException();
1420 ReacquireableGuard aGuard( m_aMutex );
1422 if( !m_xResultSetOrigin.is() )
1424 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1425 return sal_False;
1427 if( row < 0 )
1429 if( m_bFinalCount )
1431 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1432 sal_Bool bValid = sal_True;
1433 if( nNewRow <= 0 )
1435 nNewRow = 0;
1436 bValid = sal_False;
1438 m_nRow = nNewRow;
1439 m_bAfterLast = sal_False;
1440 return bValid;
1442 //unknown final count:
1443 aGuard.clear();
1445 // Solaris has problems catching or propagating derived exceptions
1446 // when only the base class is known, so make ResultSetException
1447 // (derived from SQLException) known here:
1448 sal_Bool bValid;
1451 bValid = m_xResultSetOrigin->absolute( row );
1453 catch (ResultSetException &)
1455 throw;
1458 aGuard.reacquire();
1459 if( m_bFinalCount )
1461 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1462 if( nNewRow < 0 )
1463 nNewRow = 0;
1464 m_nLastAppliedPos = nNewRow;
1465 m_nRow = nNewRow;
1466 m_bAfterLastApplied = m_bAfterLast = sal_False;
1467 return bValid;
1469 aGuard.clear();
1471 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1473 aGuard.reacquire();
1474 m_nLastAppliedPos = nCurRow;
1475 m_nRow = nCurRow;
1476 m_bAfterLast = sal_False;
1477 return nCurRow != 0;
1479 //row > 0:
1480 if( m_bFinalCount )
1482 if( row > m_nKnownCount )
1484 m_nRow = m_nKnownCount + 1;
1485 m_bAfterLast = sal_True;
1486 return sal_False;
1488 m_nRow = row;
1489 m_bAfterLast = sal_False;
1490 return sal_True;
1492 //unknown new position:
1493 aGuard.clear();
1495 sal_Bool bValid = m_xResultSetOrigin->absolute( row );
1497 aGuard.reacquire();
1498 if( m_bFinalCount )
1500 sal_Int32 nNewRow = row;
1501 if( nNewRow > m_nKnownCount )
1503 nNewRow = m_nKnownCount + 1;
1504 m_bAfterLastApplied = m_bAfterLast = sal_True;
1506 else
1507 m_bAfterLastApplied = m_bAfterLast = sal_False;
1509 m_nLastAppliedPos = nNewRow;
1510 m_nRow = nNewRow;
1511 return bValid;
1513 aGuard.clear();
1515 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1516 sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1518 aGuard.reacquire();
1519 m_nLastAppliedPos = nCurRow;
1520 m_nRow = nCurRow;
1521 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1522 return nCurRow && !bIsAfterLast;
1525 //virtual
1526 sal_Bool SAL_CALL CachedContentResultSet
1527 ::relative( sal_Int32 rows )
1528 throw( SQLException,
1529 RuntimeException )
1531 impl_EnsureNotDisposed();
1533 if( impl_isForwardOnly() )
1534 throw SQLException();
1536 ReacquireableGuard aGuard( m_aMutex );
1537 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1538 throw SQLException();
1540 if( !rows )
1541 return sal_True;
1543 sal_Int32 nNewRow = m_nRow + rows;
1544 if( nNewRow < 0 )
1545 nNewRow = 0;
1547 if( impl_isKnownValidPosition( nNewRow ) )
1549 m_nRow = nNewRow;
1550 m_bAfterLast = sal_False;
1551 return sal_True;
1553 else
1555 //known invalid new position:
1556 if( nNewRow == 0 )
1558 m_bAfterLast = sal_False;
1559 m_nRow = 0;
1560 return sal_False;
1562 if( m_bFinalCount && nNewRow > m_nKnownCount )
1564 m_bAfterLast = sal_True;
1565 m_nRow = m_nKnownCount + 1;
1566 return sal_False;
1568 //unknown new position:
1569 aGuard.clear();
1570 sal_Bool bValid = applyPositionToOrigin( nNewRow );
1572 aGuard.reacquire();
1573 m_nRow = nNewRow;
1574 m_bAfterLast = !bValid && nNewRow > 0;
1575 return bValid;
1580 //virtual
1581 sal_Bool SAL_CALL CachedContentResultSet
1582 ::first()
1583 throw( SQLException,
1584 RuntimeException )
1586 impl_EnsureNotDisposed();
1588 if( impl_isForwardOnly() )
1589 throw SQLException();
1591 ReacquireableGuard aGuard( m_aMutex );
1592 if( impl_isKnownValidPosition( 1 ) )
1594 m_nRow = 1;
1595 m_bAfterLast = sal_False;
1596 return sal_True;
1598 if( impl_isKnownInvalidPosition( 1 ) )
1600 m_nRow = 1;
1601 m_bAfterLast = sal_False;
1602 return sal_False;
1604 //unknown position
1605 aGuard.clear();
1607 sal_Bool bValid = applyPositionToOrigin( 1 );
1609 aGuard.reacquire();
1610 m_nRow = 1;
1611 m_bAfterLast = sal_False;
1612 return bValid;
1615 //virtual
1616 sal_Bool SAL_CALL CachedContentResultSet
1617 ::last()
1618 throw( SQLException,
1619 RuntimeException )
1621 impl_EnsureNotDisposed();
1623 if( impl_isForwardOnly() )
1624 throw SQLException();
1626 ReacquireableGuard aGuard( m_aMutex );
1627 if( m_bFinalCount )
1629 m_nRow = m_nKnownCount;
1630 m_bAfterLast = sal_False;
1631 return m_nKnownCount != 0;
1633 //unknown position
1634 if( !m_xResultSetOrigin.is() )
1636 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1637 return sal_False;
1639 aGuard.clear();
1641 sal_Bool bValid = m_xResultSetOrigin->last();
1643 aGuard.reacquire();
1644 m_bAfterLastApplied = m_bAfterLast = sal_False;
1645 if( m_bFinalCount )
1647 m_nLastAppliedPos = m_nKnownCount;
1648 m_nRow = m_nKnownCount;
1649 return bValid;
1651 aGuard.clear();
1653 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1655 aGuard.reacquire();
1656 m_nLastAppliedPos = nCurRow;
1657 m_nRow = nCurRow;
1658 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1659 m_nKnownCount = nCurRow;
1660 m_bFinalCount = sal_True;
1661 return nCurRow != 0;
1664 //virtual
1665 void SAL_CALL CachedContentResultSet
1666 ::beforeFirst()
1667 throw( SQLException,
1668 RuntimeException )
1670 impl_EnsureNotDisposed();
1672 if( impl_isForwardOnly() )
1673 throw SQLException();
1675 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1676 m_nRow = 0;
1677 m_bAfterLast = sal_False;
1680 //virtual
1681 void SAL_CALL CachedContentResultSet
1682 ::afterLast()
1683 throw( SQLException,
1684 RuntimeException )
1686 impl_EnsureNotDisposed();
1688 if( impl_isForwardOnly() )
1689 throw SQLException();
1691 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1692 m_nRow = 1;
1693 m_bAfterLast = sal_True;
1696 //virtual
1697 sal_Bool SAL_CALL CachedContentResultSet
1698 ::isAfterLast()
1699 throw( SQLException,
1700 RuntimeException )
1702 impl_EnsureNotDisposed();
1704 ReacquireableGuard aGuard( m_aMutex );
1705 if( !m_bAfterLast )
1706 return sal_False;
1707 if( m_nKnownCount )
1708 return m_bAfterLast;
1709 if( m_bFinalCount )
1710 return sal_False;
1712 if( !m_xResultSetOrigin.is() )
1714 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1715 return sal_False;
1717 aGuard.clear();
1719 //find out whethter the original resultset contains rows or not
1720 m_xResultSetOrigin->afterLast();
1722 aGuard.reacquire();
1723 m_bAfterLastApplied = sal_True;
1724 aGuard.clear();
1726 return m_xResultSetOrigin->isAfterLast();
1729 //virtual
1730 sal_Bool SAL_CALL CachedContentResultSet
1731 ::isBeforeFirst()
1732 throw( SQLException,
1733 RuntimeException )
1735 impl_EnsureNotDisposed();
1737 ReacquireableGuard aGuard( m_aMutex );
1738 if( m_bAfterLast )
1739 return sal_False;
1740 if( m_nRow )
1741 return sal_False;
1742 if( m_nKnownCount )
1743 return !m_nRow;
1744 if( m_bFinalCount )
1745 return sal_False;
1747 if( !m_xResultSetOrigin.is() )
1749 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1750 return sal_False;
1752 aGuard.clear();
1754 //find out whethter the original resultset contains rows or not
1755 m_xResultSetOrigin->beforeFirst();
1757 aGuard.reacquire();
1758 m_bAfterLastApplied = sal_False;
1759 m_nLastAppliedPos = 0;
1760 aGuard.clear();
1762 return m_xResultSetOrigin->isBeforeFirst();
1765 //virtual
1766 sal_Bool SAL_CALL CachedContentResultSet
1767 ::isFirst()
1768 throw( SQLException,
1769 RuntimeException )
1771 impl_EnsureNotDisposed();
1773 sal_Int32 nRow = 0;
1774 Reference< XResultSet > xResultSetOrigin;
1777 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1778 if( m_bAfterLast )
1779 return sal_False;
1780 if( m_nRow != 1 )
1781 return sal_False;
1782 if( m_nKnownCount )
1783 return m_nRow == 1;
1784 if( m_bFinalCount )
1785 return sal_False;
1787 nRow = m_nRow;
1788 xResultSetOrigin = m_xResultSetOrigin;
1791 //need to ask origin
1793 if( applyPositionToOrigin( nRow ) )
1794 return xResultSetOrigin->isFirst();
1795 else
1796 return sal_False;
1800 //virtual
1801 sal_Bool SAL_CALL CachedContentResultSet
1802 ::isLast()
1803 throw( SQLException,
1804 RuntimeException )
1806 impl_EnsureNotDisposed();
1808 sal_Int32 nRow = 0;
1809 Reference< XResultSet > xResultSetOrigin;
1811 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1812 if( m_bAfterLast )
1813 return sal_False;
1814 if( m_nRow < m_nKnownCount )
1815 return sal_False;
1816 if( m_bFinalCount )
1817 return m_nKnownCount && m_nRow == m_nKnownCount;
1819 nRow = m_nRow;
1820 xResultSetOrigin = m_xResultSetOrigin;
1823 //need to ask origin
1825 if( applyPositionToOrigin( nRow ) )
1826 return xResultSetOrigin->isLast();
1827 else
1828 return sal_False;
1833 //virtual
1834 sal_Int32 SAL_CALL CachedContentResultSet
1835 ::getRow()
1836 throw( SQLException,
1837 RuntimeException )
1839 impl_EnsureNotDisposed();
1841 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1842 if( m_bAfterLast )
1843 return 0;
1844 return m_nRow;
1847 //virtual
1848 void SAL_CALL CachedContentResultSet
1849 ::refreshRow()
1850 throw( SQLException,
1851 RuntimeException )
1853 impl_EnsureNotDisposed();
1855 //the ContentResultSet is static and will not change
1856 //therefore we don't need to reload anything
1859 //virtual
1860 sal_Bool SAL_CALL CachedContentResultSet
1861 ::rowUpdated()
1862 throw( SQLException,
1863 RuntimeException )
1865 impl_EnsureNotDisposed();
1867 //the ContentResultSet is static and will not change
1868 return sal_False;
1870 //virtual
1871 sal_Bool SAL_CALL CachedContentResultSet
1872 ::rowInserted()
1873 throw( SQLException,
1874 RuntimeException )
1876 impl_EnsureNotDisposed();
1878 //the ContentResultSet is static and will not change
1879 return sal_False;
1882 //virtual
1883 sal_Bool SAL_CALL CachedContentResultSet
1884 ::rowDeleted()
1885 throw( SQLException,
1886 RuntimeException )
1888 impl_EnsureNotDisposed();
1890 //the ContentResultSet is static and will not change
1891 return sal_False;
1894 //virtual
1895 Reference< XInterface > SAL_CALL CachedContentResultSet
1896 ::getStatement()
1897 throw( SQLException,
1898 RuntimeException )
1900 impl_EnsureNotDisposed();
1901 //@todo ?return anything
1902 return Reference< XInterface >();
1905 //-----------------------------------------------------------------
1906 // XRow methods. ( inherited )
1907 //-----------------------------------------------------------------
1909 //virtual
1910 sal_Bool SAL_CALL CachedContentResultSet
1911 ::wasNull()
1912 throw( SQLException,
1913 RuntimeException )
1915 impl_EnsureNotDisposed();
1916 impl_init_xRowOrigin();
1918 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1919 if( m_bLastReadWasFromCache )
1920 return m_bLastCachedReadWasNull;
1921 if( !m_xRowOrigin.is() )
1923 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1924 return sal_False;
1927 return m_xRowOrigin->wasNull();
1930 //virtual
1931 rtl::OUString SAL_CALL CachedContentResultSet
1932 ::getString( sal_Int32 columnIndex )
1933 throw( SQLException,
1934 RuntimeException )
1936 XROW_GETXXX( getString, OUString );
1939 //virtual
1940 sal_Bool SAL_CALL CachedContentResultSet
1941 ::getBoolean( sal_Int32 columnIndex )
1942 throw( SQLException,
1943 RuntimeException )
1945 XROW_GETXXX( getBoolean, sal_Bool );
1948 //virtual
1949 sal_Int8 SAL_CALL CachedContentResultSet
1950 ::getByte( sal_Int32 columnIndex )
1951 throw( SQLException,
1952 RuntimeException )
1954 XROW_GETXXX( getByte, sal_Int8 );
1957 //virtual
1958 sal_Int16 SAL_CALL CachedContentResultSet
1959 ::getShort( sal_Int32 columnIndex )
1960 throw( SQLException,
1961 RuntimeException )
1963 XROW_GETXXX( getShort, sal_Int16 );
1966 //virtual
1967 sal_Int32 SAL_CALL CachedContentResultSet
1968 ::getInt( sal_Int32 columnIndex )
1969 throw( SQLException,
1970 RuntimeException )
1972 XROW_GETXXX( getInt, sal_Int32 );
1975 //virtual
1976 sal_Int64 SAL_CALL CachedContentResultSet
1977 ::getLong( sal_Int32 columnIndex )
1978 throw( SQLException,
1979 RuntimeException )
1981 XROW_GETXXX( getLong, sal_Int64 );
1984 //virtual
1985 float SAL_CALL CachedContentResultSet
1986 ::getFloat( sal_Int32 columnIndex )
1987 throw( SQLException,
1988 RuntimeException )
1990 XROW_GETXXX( getFloat, float );
1993 //virtual
1994 double SAL_CALL CachedContentResultSet
1995 ::getDouble( sal_Int32 columnIndex )
1996 throw( SQLException,
1997 RuntimeException )
1999 XROW_GETXXX( getDouble, double );
2002 //virtual
2003 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
2004 ::getBytes( sal_Int32 columnIndex )
2005 throw( SQLException,
2006 RuntimeException )
2008 XROW_GETXXX( getBytes, Sequence< sal_Int8 > );
2011 //virtual
2012 Date SAL_CALL CachedContentResultSet
2013 ::getDate( sal_Int32 columnIndex )
2014 throw( SQLException,
2015 RuntimeException )
2017 XROW_GETXXX( getDate, Date );
2020 //virtual
2021 Time SAL_CALL CachedContentResultSet
2022 ::getTime( sal_Int32 columnIndex )
2023 throw( SQLException,
2024 RuntimeException )
2026 XROW_GETXXX( getTime, Time );
2029 //virtual
2030 DateTime SAL_CALL CachedContentResultSet
2031 ::getTimestamp( sal_Int32 columnIndex )
2032 throw( SQLException,
2033 RuntimeException )
2035 XROW_GETXXX( getTimestamp, DateTime );
2038 //virtual
2039 Reference< com::sun::star::io::XInputStream >
2040 SAL_CALL CachedContentResultSet
2041 ::getBinaryStream( sal_Int32 columnIndex )
2042 throw( SQLException,
2043 RuntimeException )
2045 XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > );
2048 //virtual
2049 Reference< com::sun::star::io::XInputStream >
2050 SAL_CALL CachedContentResultSet
2051 ::getCharacterStream( sal_Int32 columnIndex )
2052 throw( SQLException,
2053 RuntimeException )
2055 XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > );
2058 //virtual
2059 Any SAL_CALL CachedContentResultSet
2060 ::getObject( sal_Int32 columnIndex,
2061 const Reference<
2062 com::sun::star::container::XNameAccess >& typeMap )
2063 throw( SQLException,
2064 RuntimeException )
2066 //if you change this macro please pay attention to
2067 //define XROW_GETXXX, where this is similar implemented
2069 ReacquireableGuard aGuard( m_aMutex );
2070 sal_Int32 nRow = m_nRow;
2071 sal_Int32 nFetchSize = m_nFetchSize;
2072 sal_Int32 nFetchDirection = m_nFetchDirection;
2073 if( !m_aCache.hasRow( nRow ) )
2075 if( !m_aCache.hasCausedException( nRow ) )
2077 if( !m_xFetchProvider.is() )
2079 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
2080 return Any();
2082 aGuard.clear();
2084 impl_fetchData( nRow, nFetchSize, nFetchDirection );
2086 aGuard.reacquire();
2087 if( !m_aCache.hasRow( nRow ) )
2089 m_bLastReadWasFromCache = sal_False;
2090 aGuard.clear();
2091 applyPositionToOrigin( nRow );
2092 impl_init_xRowOrigin();
2093 return m_xRowOrigin->getObject( columnIndex, typeMap );
2096 //@todo: pay attention to typeMap
2097 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2098 Any aRet;
2099 m_bLastReadWasFromCache = sal_True;
2100 m_bLastCachedReadWasNull = !( rValue >>= aRet );
2101 return aRet;
2104 //virtual
2105 Reference< XRef > SAL_CALL CachedContentResultSet
2106 ::getRef( sal_Int32 columnIndex )
2107 throw( SQLException,
2108 RuntimeException )
2110 XROW_GETXXX( getRef, Reference< XRef > );
2113 //virtual
2114 Reference< XBlob > SAL_CALL CachedContentResultSet
2115 ::getBlob( sal_Int32 columnIndex )
2116 throw( SQLException,
2117 RuntimeException )
2119 XROW_GETXXX( getBlob, Reference< XBlob > );
2122 //virtual
2123 Reference< XClob > SAL_CALL CachedContentResultSet
2124 ::getClob( sal_Int32 columnIndex )
2125 throw( SQLException,
2126 RuntimeException )
2128 XROW_GETXXX( getClob, Reference< XClob > );
2131 //virtual
2132 Reference< XArray > SAL_CALL CachedContentResultSet
2133 ::getArray( sal_Int32 columnIndex )
2134 throw( SQLException,
2135 RuntimeException )
2137 XROW_GETXXX( getArray, Reference< XArray > );
2140 //-----------------------------------------------------------------
2141 // Type Converter Support
2142 //-----------------------------------------------------------------
2144 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2146 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2148 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2150 m_bTriedToGetTypeConverter = sal_True;
2151 m_xTypeConverter = Reference< XTypeConverter >(
2152 m_xSMgr->createInstance(
2153 OUString::createFromAscii(
2154 "com.sun.star.script.Converter" ) ),
2155 UNO_QUERY );
2157 OSL_ENSURE( m_xTypeConverter.is(),
2158 "PropertyValueSet::getTypeConverter() - "
2159 "Service 'com.sun.star.script.Converter' n/a!" );
2161 return m_xTypeConverter;
2164 //--------------------------------------------------------------------------
2165 //--------------------------------------------------------------------------
2166 // class CachedContentResultSetFactory
2167 //--------------------------------------------------------------------------
2168 //--------------------------------------------------------------------------
2170 CachedContentResultSetFactory::CachedContentResultSetFactory(
2171 const Reference< XMultiServiceFactory > & rSMgr )
2173 m_xSMgr = rSMgr;
2176 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2180 //--------------------------------------------------------------------------
2181 // CachedContentResultSetFactory XInterface methods.
2182 //--------------------------------------------------------------------------
2184 XINTERFACE_IMPL_3( CachedContentResultSetFactory,
2185 XTypeProvider,
2186 XServiceInfo,
2187 XCachedContentResultSetFactory );
2189 //--------------------------------------------------------------------------
2190 // CachedContentResultSetFactory XTypeProvider methods.
2191 //--------------------------------------------------------------------------
2193 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2194 XTypeProvider,
2195 XServiceInfo,
2196 XCachedContentResultSetFactory );
2198 //--------------------------------------------------------------------------
2199 // CachedContentResultSetFactory XServiceInfo methods.
2200 //--------------------------------------------------------------------------
2202 XSERVICEINFO_IMPL_1( CachedContentResultSetFactory,
2203 OUString::createFromAscii(
2204 "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2205 OUString::createFromAscii(
2206 CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2208 //--------------------------------------------------------------------------
2209 // Service factory implementation.
2210 //--------------------------------------------------------------------------
2212 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2214 //--------------------------------------------------------------------------
2215 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2216 //--------------------------------------------------------------------------
2218 //virtual
2219 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2220 ::createCachedContentResultSet(
2221 const Reference< XResultSet > & xSource,
2222 const Reference< XContentIdentifierMapping > & xMapping )
2223 throw( com::sun::star::uno::RuntimeException )
2225 Reference< XResultSet > xRet;
2226 xRet = new CachedContentResultSet( m_xSMgr, xSource, xMapping );
2227 return xRet;