Update ooo320-m1
[ooovba.git] / ucb / source / cacher / cachedcontentresultset.cxx
bloba6c3f0aa8efe15a8185e244c09e0dec5e7d50614
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cachedcontentresultset.cxx,v $
10 * $Revision: 1.14.22.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 #include <cachedcontentresultset.hxx>
35 #include <com/sun/star/sdbc/FetchDirection.hpp>
36 #include <com/sun/star/ucb/FetchError.hpp>
37 #include <com/sun/star/ucb/ResultSetException.hpp>
38 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #include <com/sun/star/script/XTypeConverter.hpp>
40 #include <com/sun/star/sdbc/ResultSetType.hpp>
41 #include <rtl/ustring.hxx>
42 #include <osl/diagnose.h>
44 using namespace com::sun::star::beans;
45 using namespace com::sun::star::lang;
46 using namespace com::sun::star::script;
47 using namespace com::sun::star::sdbc;
48 using namespace com::sun::star::ucb;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::util;
51 using namespace cppu;
52 using namespace rtl;
54 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
55 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
57 //--------------------------------------------------------------------------
58 //--------------------------------------------------------------------------
59 //define for getXXX methods of interface XRow
60 //--------------------------------------------------------------------------
61 //--------------------------------------------------------------------------
63 //if you change this macro please pay attention to
64 //function ::getObject, where this is similar implemented
66 #define XROW_GETXXX( getXXX, Type ) \
67 impl_EnsureNotDisposed(); \
68 ReacquireableGuard aGuard( m_aMutex ); \
69 sal_Int32 nRow = m_nRow; \
70 sal_Int32 nFetchSize = m_nFetchSize; \
71 sal_Int32 nFetchDirection = m_nFetchDirection; \
72 if( !m_aCache.hasRow( nRow ) ) \
73 { \
74 if( !m_aCache.hasCausedException( nRow ) ) \
75 { \
76 if( !m_xFetchProvider.is() ) \
77 { \
78 OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \
79 throw SQLException(); \
80 } \
81 aGuard.clear(); \
82 if( impl_isForwardOnly() ) \
83 applyPositionToOrigin( nRow ); \
85 impl_fetchData( nRow, nFetchSize, nFetchDirection ); \
86 } \
87 aGuard.reacquire(); \
88 if( !m_aCache.hasRow( nRow ) ) \
89 { \
90 m_bLastReadWasFromCache = sal_False; \
91 aGuard.clear(); \
92 applyPositionToOrigin( nRow ); \
93 impl_init_xRowOrigin(); \
94 return m_xRowOrigin->getXXX( columnIndex ); \
95 } \
96 } \
97 const Any& rValue = m_aCache.getAny( nRow, columnIndex );\
98 Type aRet = Type(); \
99 m_bLastReadWasFromCache = sal_True; \
100 m_bLastCachedReadWasNull = !( rValue >>= aRet ); \
101 /* Last chance. Try type converter service... */ \
102 if ( m_bLastCachedReadWasNull && rValue.hasValue() ) \
104 Reference< XTypeConverter > xConverter \
105 = getTypeConverter(); \
106 if ( xConverter.is() ) \
108 try \
110 Any aConvAny = xConverter->convertTo( \
111 rValue, \
112 getCppuType( static_cast< \
113 const Type * >( 0 ) ) ); \
114 m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \
116 catch ( IllegalArgumentException ) \
119 catch ( CannotConvertException ) \
124 return aRet;
126 //--------------------------------------------------------------------------
127 //--------------------------------------------------------------------------
128 // CCRS_Cache methoeds.
129 //--------------------------------------------------------------------------
130 //--------------------------------------------------------------------------
132 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
133 const Reference< XContentIdentifierMapping > & xMapping )
134 : m_pResult( NULL )
135 , m_xContentIdentifierMapping( xMapping )
136 , m_pMappedReminder( NULL )
140 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
142 delete m_pResult;
145 void SAL_CALL CachedContentResultSet::CCRS_Cache
146 ::clear()
148 if( m_pResult )
150 delete m_pResult;
151 m_pResult = NULL;
153 clearMappedReminder();
156 void SAL_CALL CachedContentResultSet::CCRS_Cache
157 ::loadData( const FetchResult& rResult )
159 clear();
160 m_pResult = new FetchResult( rResult );
163 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
164 ::hasRow( sal_Int32 row )
166 if( !m_pResult )
167 return sal_False;
168 long nStart = m_pResult->StartIndex;
169 long nEnd = nStart;
170 if( m_pResult->Orientation )
171 nEnd += m_pResult->Rows.getLength() - 1;
172 else
173 nStart -= m_pResult->Rows.getLength() + 1;
175 return nStart <= row && row <= nEnd;
178 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
179 ::getMaxRow()
181 if( !m_pResult )
182 return 0;
183 long nEnd = m_pResult->StartIndex;
184 if( m_pResult->Orientation )
185 return nEnd += m_pResult->Rows.getLength() - 1;
186 else
187 return nEnd;
190 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
191 ::hasKnownLast()
193 if( !m_pResult )
194 return sal_False;
196 if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
197 && m_pResult->Orientation
198 && m_pResult->Rows.getLength() )
199 return sal_True;
201 return sal_False;
204 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
205 ::hasCausedException( sal_Int32 nRow )
207 if( !m_pResult )
208 return sal_False;
209 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
210 return sal_False;
212 long nEnd = m_pResult->StartIndex;
213 if( m_pResult->Orientation )
214 nEnd += m_pResult->Rows.getLength();
216 return nRow == nEnd+1;
219 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
220 ::getRowAny( sal_Int32 nRow )
221 throw( SQLException,
222 RuntimeException )
224 if( !nRow )
225 throw SQLException();
226 if( !m_pResult )
227 throw SQLException();
228 if( !hasRow( nRow ) )
229 throw SQLException();
231 long nDiff = nRow - m_pResult->StartIndex;
232 if( nDiff < 0 )
233 nDiff *= -1;
235 return (m_pResult->Rows)[nDiff];
238 void SAL_CALL CachedContentResultSet::CCRS_Cache
239 ::remindMapped( sal_Int32 nRow )
241 //remind that this row was mapped
242 if( !m_pResult )
243 return;
244 long nDiff = nRow - m_pResult->StartIndex;
245 if( nDiff < 0 )
246 nDiff *= -1;
247 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
248 if( nDiff < pMappedReminder->getLength() )
249 (*pMappedReminder)[nDiff] = sal_True;
252 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
253 ::isRowMapped( sal_Int32 nRow )
255 if( !m_pMappedReminder || !m_pResult )
256 return sal_False;
257 long nDiff = nRow - m_pResult->StartIndex;
258 if( nDiff < 0 )
259 nDiff *= -1;
260 if( nDiff < m_pMappedReminder->getLength() )
261 return (*m_pMappedReminder)[nDiff];
262 return sal_False;
265 void SAL_CALL CachedContentResultSet::CCRS_Cache
266 ::clearMappedReminder()
268 delete m_pMappedReminder;
269 m_pMappedReminder = NULL;
272 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
273 ::getMappedReminder()
275 if( !m_pMappedReminder )
277 sal_Int32 nCount = m_pResult->Rows.getLength();
278 m_pMappedReminder = new Sequence< sal_Bool >( nCount );
279 for( ;nCount; nCount-- )
280 (*m_pMappedReminder)[nCount] = sal_False;
282 return m_pMappedReminder;
285 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
286 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
287 throw( SQLException,
288 RuntimeException )
290 if( !nColumnIndex )
291 throw SQLException();
292 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
294 Any& rRow = getRowAny( nRow );
295 Sequence< Any > aValue;
296 rRow >>= aValue;
297 if( m_xContentIdentifierMapping->mapRow( aValue ) )
299 rRow <<= aValue;
300 remindMapped( nRow );
302 else
303 m_xContentIdentifierMapping.clear();
305 const Sequence< Any >& rRow =
306 (* reinterpret_cast< const Sequence< Any > * >
307 (getRowAny( nRow ).getValue() ));
309 if( nColumnIndex > rRow.getLength() )
310 throw SQLException();
311 return rRow[nColumnIndex-1];
314 const rtl::OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
315 ::getContentIdentifierString( sal_Int32 nRow )
316 throw( com::sun::star::uno::RuntimeException )
320 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
322 Any& rRow = getRowAny( nRow );
323 rtl::OUString aValue;
324 rRow >>= aValue;
325 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
326 remindMapped( nRow );
328 return (* reinterpret_cast< const rtl::OUString * >
329 (getRowAny( nRow ).getValue() ));
331 catch( SQLException )
333 throw RuntimeException();
337 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
338 ::getContentIdentifier( sal_Int32 nRow )
339 throw( com::sun::star::uno::RuntimeException )
343 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
345 Any& rRow = getRowAny( nRow );
346 Reference< XContentIdentifier > aValue;
347 rRow >>= aValue;
348 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
349 remindMapped( nRow );
351 return (* reinterpret_cast< const Reference< XContentIdentifier > * >
352 (getRowAny( nRow ).getValue() ));
354 catch( SQLException )
356 throw RuntimeException();
360 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
361 ::getContent( sal_Int32 nRow )
362 throw( com::sun::star::uno::RuntimeException )
366 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
368 Any& rRow = getRowAny( nRow );
369 Reference< XContent > aValue;
370 rRow >>= aValue;
371 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
372 remindMapped( nRow );
374 return (* reinterpret_cast< const Reference< XContent > * >
375 (getRowAny( nRow ).getValue() ));
377 catch( SQLException )
379 throw RuntimeException();
383 //--------------------------------------------------------------------------
384 //--------------------------------------------------------------------------
385 // class CCRS_PropertySetInfo
386 //--------------------------------------------------------------------------
387 //--------------------------------------------------------------------------
389 class CCRS_PropertySetInfo :
390 public cppu::OWeakObject,
391 public com::sun::star::lang::XTypeProvider,
392 public com::sun::star::beans::XPropertySetInfo
394 friend class CachedContentResultSet;
396 //my Properties
397 Sequence< com::sun::star::beans::Property >*
398 m_pProperties;
400 //some helping variables ( names for my special properties )
401 static rtl::OUString m_aPropertyNameForCount;
402 static rtl::OUString m_aPropertyNameForFinalCount;
403 static rtl::OUString m_aPropertyNameForFetchSize;
404 static rtl::OUString m_aPropertyNameForFetchDirection;
406 long m_nFetchSizePropertyHandle;
407 long m_nFetchDirectionPropertyHandle;
409 private:
410 sal_Int32 SAL_CALL
411 impl_getRemainedHandle() const;
413 sal_Bool SAL_CALL
414 impl_queryProperty(
415 const rtl::OUString& rName
416 , com::sun::star::beans::Property& rProp ) const;
417 sal_Int32 SAL_CALL
418 impl_getPos( const rtl::OUString& rName ) const;
420 static sal_Bool SAL_CALL
421 impl_isMyPropertyName( const rtl::OUString& rName );
423 public:
424 CCRS_PropertySetInfo( Reference<
425 XPropertySetInfo > xPropertySetInfoOrigin );
427 virtual ~CCRS_PropertySetInfo();
429 // XInterface
430 XINTERFACE_DECL()
432 // XTypeProvider
433 XTYPEPROVIDER_DECL()
435 // XPropertySetInfo
436 virtual Sequence< com::sun::star::beans::Property > SAL_CALL
437 getProperties()
438 throw( RuntimeException );
440 virtual com::sun::star::beans::Property SAL_CALL
441 getPropertyByName( const rtl::OUString& aName )
442 throw( com::sun::star::beans::UnknownPropertyException, RuntimeException );
444 virtual sal_Bool SAL_CALL
445 hasPropertyByName( const rtl::OUString& Name )
446 throw( RuntimeException );
449 OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( OUString::createFromAscii( "RowCount" ) );
450 OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( OUString::createFromAscii( "IsRowCountFinal" ) );
451 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) );
452 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) );
454 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
455 Reference< XPropertySetInfo > xInfo )
456 : m_pProperties( NULL )
457 , m_nFetchSizePropertyHandle( -1 )
458 , m_nFetchDirectionPropertyHandle( -1 )
460 //initialize list of properties:
462 // it is required, that the received xInfo contains the two
463 // properties with names 'm_aPropertyNameForCount' and
464 // 'm_aPropertyNameForFinalCount'
466 if( xInfo.is() )
468 Sequence<Property> aProps = xInfo->getProperties();
469 m_pProperties = new Sequence<Property> ( aProps );
471 else
473 OSL_ENSURE( sal_False, "The received XPropertySetInfo doesn't contain required properties" );
474 m_pProperties = new Sequence<Property>;
477 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
478 sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
479 sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
480 sal_Int32 nDeleted = 0;
481 if( nFetchSize != -1 )
482 nDeleted++;
483 if( nFetchDirection != -1 )
484 nDeleted++;
486 Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
487 sal_Int32 nOrigProps = pOrigProps->getLength();
489 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
490 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
492 if( n == nFetchSize || n == nFetchDirection )
493 m--;
494 else
495 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
498 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
499 rMyProp.Name = m_aPropertyNameForFetchSize;
500 rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) );
501 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
503 if( nFetchSize != -1 )
504 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
505 else
506 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
508 rMyProp.Handle = m_nFetchSizePropertyHandle;
512 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
513 rMyProp.Name = m_aPropertyNameForFetchDirection;
514 rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) );
515 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
517 if( nFetchSize != -1 )
518 m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
519 else
520 m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
522 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
524 delete pOrigProps;
527 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
529 delete m_pProperties;
532 //--------------------------------------------------------------------------
533 // XInterface methods.
534 //--------------------------------------------------------------------------
535 //list all interfaces inclusive baseclasses of interfaces
536 XINTERFACE_IMPL_2( CCRS_PropertySetInfo
537 , XTypeProvider
538 , XPropertySetInfo
541 //--------------------------------------------------------------------------
542 // XTypeProvider methods.
543 //--------------------------------------------------------------------------
544 //list all interfaces exclusive baseclasses
545 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
546 , XTypeProvider
547 , XPropertySetInfo
549 //--------------------------------------------------------------------------
550 // XPropertySetInfo methods.
551 //--------------------------------------------------------------------------
552 //virtual
553 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
554 ::getProperties() throw( RuntimeException )
556 return *m_pProperties;
559 //virtual
560 Property SAL_CALL CCRS_PropertySetInfo
561 ::getPropertyByName( const rtl::OUString& aName )
562 throw( UnknownPropertyException, RuntimeException )
564 if ( !aName.getLength() )
565 throw UnknownPropertyException();
567 Property aProp;
568 if ( impl_queryProperty( aName, aProp ) )
569 return aProp;
571 throw UnknownPropertyException();
574 //virtual
575 sal_Bool SAL_CALL CCRS_PropertySetInfo
576 ::hasPropertyByName( const rtl::OUString& Name )
577 throw( RuntimeException )
579 return ( impl_getPos( Name ) != -1 );
582 //--------------------------------------------------------------------------
583 // impl_ methods.
584 //--------------------------------------------------------------------------
586 sal_Int32 SAL_CALL CCRS_PropertySetInfo
587 ::impl_getPos( const OUString& rName ) const
589 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
591 const Property& rMyProp = (*m_pProperties)[nN];
592 if( rMyProp.Name == rName )
593 return nN;
595 return -1;
598 sal_Bool SAL_CALL CCRS_PropertySetInfo
599 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
601 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
603 const Property& rMyProp = (*m_pProperties)[nN];
604 if( rMyProp.Name == rName )
606 rProp.Name = rMyProp.Name;
607 rProp.Handle = rMyProp.Handle;
608 rProp.Type = rMyProp.Type;
609 rProp.Attributes = rMyProp.Attributes;
611 return sal_True;
614 return sal_False;
617 //static
618 sal_Bool SAL_CALL CCRS_PropertySetInfo
619 ::impl_isMyPropertyName( const OUString& rPropertyName )
621 return ( rPropertyName == m_aPropertyNameForCount
622 || rPropertyName == m_aPropertyNameForFinalCount
623 || rPropertyName == m_aPropertyNameForFetchSize
624 || rPropertyName == m_aPropertyNameForFetchDirection );
627 sal_Int32 SAL_CALL CCRS_PropertySetInfo
628 ::impl_getRemainedHandle( ) const
630 sal_Int32 nHandle = 1;
632 if( !m_pProperties )
634 OSL_ENSURE( sal_False, "Properties not initialized yet" );
635 return nHandle;
637 sal_Bool bFound = sal_True;
638 while( bFound )
640 bFound = sal_False;
641 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
643 if( nHandle == (*m_pProperties)[nN].Handle )
645 bFound = sal_True;
646 nHandle++;
647 break;
651 return nHandle;
654 //--------------------------------------------------------------------------
655 //--------------------------------------------------------------------------
656 // class CachedContentResultSet
657 //--------------------------------------------------------------------------
658 //--------------------------------------------------------------------------
660 CachedContentResultSet::CachedContentResultSet(
661 const Reference< XMultiServiceFactory > & xSMgr
662 , const Reference< XResultSet > & xOrigin
663 , const Reference< XContentIdentifierMapping > &
664 xContentIdentifierMapping )
665 : ContentResultSetWrapper( xOrigin )
667 , m_xSMgr( xSMgr )
668 , m_xFetchProvider( NULL )
669 , m_xFetchProviderForContentAccess( NULL )
671 , m_xMyPropertySetInfo( NULL )
672 , m_pMyPropSetInfo( NULL )
674 , m_xContentIdentifierMapping( xContentIdentifierMapping )
675 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
676 , m_bAfterLast( sal_False )
677 , m_nLastAppliedPos( 0 )
678 , m_bAfterLastApplied( sal_False )
679 , m_nKnownCount( 0 )
680 , m_bFinalCount( sal_False )
681 , m_nFetchSize(
682 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
683 , m_nFetchDirection(
684 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
686 , m_bLastReadWasFromCache( sal_False )
687 , m_bLastCachedReadWasNull( sal_True )
688 , m_aCache( m_xContentIdentifierMapping )
689 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
690 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
691 , m_aCacheContent( m_xContentIdentifierMapping )
692 , m_bTriedToGetTypeConverter( sal_False )
693 , m_xTypeConverter( NULL )
695 m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
696 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
698 m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
699 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
701 impl_init();
704 CachedContentResultSet::~CachedContentResultSet()
706 impl_deinit();
707 //do not delete m_pMyPropSetInfo, cause it is hold via reference
710 //--------------------------------------------------------------------------
711 // impl_ methods.
712 //--------------------------------------------------------------------------
714 sal_Bool SAL_CALL CachedContentResultSet
715 ::applyPositionToOrigin( sal_Int32 nRow )
716 throw( SQLException,
717 RuntimeException )
719 impl_EnsureNotDisposed();
720 //-------------------------------------------------------------------------
722 @returns
723 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
724 the result set.
727 ReacquireableGuard aGuard( m_aMutex );
728 OSL_ENSURE( nRow >= 0, "only positive values supported" );
729 if( !m_xResultSetOrigin.is() )
731 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
732 return sal_False;
734 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
736 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
737 sal_Bool bAfterLastApplied = m_bAfterLastApplied;
738 sal_Bool bAfterLast = m_bAfterLast;
739 sal_Int32 nForwardOnly = m_nForwardOnly;
741 aGuard.clear();
743 if( bAfterLastApplied || nLastAppliedPos != nRow )
745 if( nForwardOnly == 1 )
747 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
748 throw SQLException();
750 sal_Int32 nN = nRow - nLastAppliedPos;
751 sal_Int32 nM;
752 for( nM = 0; nN--; nM++ )
754 if( !m_xResultSetOrigin->next() )
755 break;
758 aGuard.reacquire();
759 m_nLastAppliedPos += nM;
760 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
761 return nRow == m_nLastAppliedPos;
764 if( !nRow ) //absolute( 0 ) will throw exception
766 m_xResultSetOrigin->beforeFirst();
768 aGuard.reacquire();
769 m_nLastAppliedPos = 0;
770 m_bAfterLastApplied = sal_False;
771 return sal_False;
775 //move absolute, if !nLastAppliedPos
776 //because move relative would throw exception
777 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
779 sal_Bool bValid = m_xResultSetOrigin->absolute( nRow );
781 aGuard.reacquire();
782 m_nLastAppliedPos = nRow;
783 m_bAfterLastApplied = !bValid;
784 return bValid;
786 else
788 sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
790 aGuard.reacquire();
791 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
792 m_bAfterLastApplied = !bValid;
793 return bValid;
796 catch( SQLException& rEx )
798 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
800 sal_Int32 nN = nRow - nLastAppliedPos;
801 sal_Int32 nM;
802 for( nM = 0; nN--; nM++ )
804 if( !m_xResultSetOrigin->next() )
805 break;
808 aGuard.reacquire();
809 m_nLastAppliedPos += nM;
810 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
812 else
813 throw rEx;
816 return nRow == m_nLastAppliedPos;
818 return sal_True;
821 //--------------------------------------------------------------------------
822 //--------------------------------------------------------------------------
823 //define for fetching data
824 //--------------------------------------------------------------------------
825 //--------------------------------------------------------------------------
827 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
828 sal_Bool bDirection = !!( \
829 nFetchDirection != FetchDirection::REVERSE ); \
830 FetchResult aResult = \
831 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
832 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
833 aCache.loadData( aResult ); \
834 sal_Int32 nMax = aCache.getMaxRow(); \
835 sal_Int32 nCurCount = m_nKnownCount; \
836 sal_Bool bIsFinalCount = aCache.hasKnownLast(); \
837 sal_Bool bCurIsFinalCount = m_bFinalCount; \
838 aGuard2.clear(); \
839 if( nMax > nCurCount ) \
840 impl_changeRowCount( nCurCount, nMax ); \
841 if( bIsFinalCount && !bCurIsFinalCount ) \
842 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
844 void SAL_CALL CachedContentResultSet
845 ::impl_fetchData( sal_Int32 nRow
846 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
847 throw( com::sun::star::uno::RuntimeException )
849 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
852 void SAL_CALL CachedContentResultSet
853 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
855 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
856 if( nNew <= nOld )
857 return;
859 //create PropertyChangeEvent and set value
860 PropertyChangeEvent aEvt;
862 osl::Guard< osl::Mutex > aGuard( m_aMutex );
863 aEvt.Source = static_cast< XPropertySet * >( this );
864 aEvt.Further = sal_False;
865 aEvt.OldValue <<= nOld;
866 aEvt.NewValue <<= nNew;
868 m_nKnownCount = nNew;
871 //send PropertyChangeEvent to listeners
872 impl_notifyPropertyChangeListeners( aEvt );
875 void SAL_CALL CachedContentResultSet
876 ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew )
878 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
879 if( ! (!bOld && bNew ) )
880 return;
882 //create PropertyChangeEvent and set value
883 PropertyChangeEvent aEvt;
885 osl::Guard< osl::Mutex > aGuard( m_aMutex );
886 aEvt.Source = static_cast< XPropertySet * >( this );
887 aEvt.Further = sal_False;
888 aEvt.OldValue <<= bOld;
889 aEvt.NewValue <<= bNew;
891 m_bFinalCount = bNew;
894 //send PropertyChangeEvent to listeners
895 impl_notifyPropertyChangeListeners( aEvt );
898 sal_Bool SAL_CALL CachedContentResultSet
899 ::impl_isKnownValidPosition( sal_Int32 nRow )
901 return m_nKnownCount && nRow
902 && nRow <= m_nKnownCount;
905 sal_Bool SAL_CALL CachedContentResultSet
906 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
908 if( !nRow )
909 return sal_True;
910 if( !m_bFinalCount )
911 return sal_False;
912 return nRow > m_nKnownCount;
916 //virtual
917 void SAL_CALL CachedContentResultSet
918 ::impl_initPropertySetInfo()
920 ContentResultSetWrapper::impl_initPropertySetInfo();
922 osl::Guard< osl::Mutex > aGuard( m_aMutex );
923 if( m_pMyPropSetInfo )
924 return;
925 m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
926 m_xMyPropertySetInfo = m_pMyPropSetInfo;
927 m_xPropertySetInfo = m_xMyPropertySetInfo;
930 //--------------------------------------------------------------------------
931 // XInterface methods. ( inherited )
932 //--------------------------------------------------------------------------
933 XINTERFACE_COMMON_IMPL( CachedContentResultSet )
935 Any SAL_CALL CachedContentResultSet
936 ::queryInterface( const Type& rType )
937 throw ( RuntimeException )
939 //list all interfaces inclusive baseclasses of interfaces
941 Any aRet = ContentResultSetWrapper::queryInterface( rType );
942 if( aRet.hasValue() )
943 return aRet;
945 aRet = cppu::queryInterface( rType,
946 static_cast< XTypeProvider* >( this ),
947 static_cast< XServiceInfo* >( this ) );
949 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
952 //--------------------------------------------------------------------------
953 // XTypeProvider methods.
954 //--------------------------------------------------------------------------
955 //list all interfaces exclusive baseclasses
956 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
957 , XTypeProvider
958 , XServiceInfo
959 , XComponent
960 , XCloseable
961 , XResultSetMetaDataSupplier
962 , XPropertySet
964 , XPropertyChangeListener
965 , XVetoableChangeListener
967 , XContentAccess
969 , XResultSet
970 , XRow );
972 //--------------------------------------------------------------------------
973 // XServiceInfo methods.
974 //--------------------------------------------------------------------------
976 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
977 OUString::createFromAscii(
978 "com.sun.star.comp.ucb.CachedContentResultSet" ),
979 OUString::createFromAscii(
980 CACHED_CONTENT_RESULTSET_SERVICE_NAME ) );
982 //--------------------------------------------------------------------------
983 // XPropertySet methods. ( inherited )
984 //--------------------------------------------------------------------------
986 // virtual
987 void SAL_CALL CachedContentResultSet
988 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
989 throw( UnknownPropertyException,
990 PropertyVetoException,
991 IllegalArgumentException,
992 WrappedTargetException,
993 RuntimeException )
995 impl_EnsureNotDisposed();
997 if( !getPropertySetInfo().is() )
999 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1000 throw UnknownPropertyException();
1003 Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
1004 //throws UnknownPropertyException, if so
1006 if( aProp.Attributes & PropertyAttribute::READONLY )
1008 //It is assumed, that the properties
1009 //'RowCount' and 'IsRowCountFinal' are readonly!
1010 throw IllegalArgumentException();
1012 if( aProp.Name == CCRS_PropertySetInfo
1013 ::m_aPropertyNameForFetchDirection )
1015 //check value
1016 sal_Int32 nNew;
1017 if( !( aValue >>= nNew ) )
1019 throw IllegalArgumentException();
1022 if( nNew == FetchDirection::UNKNOWN )
1024 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1026 else if( !( nNew == FetchDirection::FORWARD
1027 || nNew == FetchDirection::REVERSE ) )
1029 throw IllegalArgumentException();
1032 //create PropertyChangeEvent and set value
1033 PropertyChangeEvent aEvt;
1035 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1036 aEvt.Source = static_cast< XPropertySet * >( this );
1037 aEvt.PropertyName = aPropertyName;
1038 aEvt.Further = sal_False;
1039 aEvt.PropertyHandle = m_pMyPropSetInfo->
1040 m_nFetchDirectionPropertyHandle;
1041 aEvt.OldValue <<= m_nFetchDirection;
1042 aEvt.NewValue <<= nNew;
1044 m_nFetchDirection = nNew;
1047 //send PropertyChangeEvent to listeners
1048 impl_notifyPropertyChangeListeners( aEvt );
1050 else if( aProp.Name == CCRS_PropertySetInfo
1051 ::m_aPropertyNameForFetchSize )
1053 //check value
1054 sal_Int32 nNew;
1055 if( !( aValue >>= nNew ) )
1057 throw IllegalArgumentException();
1060 if( nNew < 0 )
1062 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1065 //create PropertyChangeEvent and set value
1066 PropertyChangeEvent aEvt;
1068 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1069 aEvt.Source = static_cast< XPropertySet * >( this );
1070 aEvt.PropertyName = aPropertyName;
1071 aEvt.Further = sal_False;
1072 aEvt.PropertyHandle = m_pMyPropSetInfo->
1073 m_nFetchSizePropertyHandle;
1074 aEvt.OldValue <<= m_nFetchSize;
1075 aEvt.NewValue <<= nNew;
1077 m_nFetchSize = nNew;
1080 //send PropertyChangeEvent to listeners
1081 impl_notifyPropertyChangeListeners( aEvt );
1083 else
1085 impl_init_xPropertySetOrigin();
1087 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1088 if( !m_xPropertySetOrigin.is() )
1090 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1091 return;
1094 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1098 //--------------------------------------------------------------------------
1099 // virtual
1100 Any SAL_CALL CachedContentResultSet
1101 ::getPropertyValue( const OUString& rPropertyName )
1102 throw( UnknownPropertyException,
1103 WrappedTargetException,
1104 RuntimeException )
1106 impl_EnsureNotDisposed();
1108 if( !getPropertySetInfo().is() )
1110 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1111 throw UnknownPropertyException();
1114 Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1115 //throws UnknownPropertyException, if so
1117 Any aValue;
1118 if( rPropertyName == CCRS_PropertySetInfo
1119 ::m_aPropertyNameForCount )
1121 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1122 aValue <<= m_nKnownCount;
1124 else if( rPropertyName == CCRS_PropertySetInfo
1125 ::m_aPropertyNameForFinalCount )
1127 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1128 aValue <<= m_bFinalCount;
1130 else if( rPropertyName == CCRS_PropertySetInfo
1131 ::m_aPropertyNameForFetchSize )
1133 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1134 aValue <<= m_nFetchSize;
1136 else if( rPropertyName == CCRS_PropertySetInfo
1137 ::m_aPropertyNameForFetchDirection )
1139 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1140 aValue <<= m_nFetchDirection;
1142 else
1144 impl_init_xPropertySetOrigin();
1146 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1147 if( !m_xPropertySetOrigin.is() )
1149 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1150 throw UnknownPropertyException();
1153 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1155 return aValue;
1158 //--------------------------------------------------------------------------
1159 // own methods. ( inherited )
1160 //--------------------------------------------------------------------------
1162 //virtual
1163 void SAL_CALL CachedContentResultSet
1164 ::impl_disposing( const EventObject& rEventObject )
1165 throw( RuntimeException )
1168 impl_EnsureNotDisposed();
1169 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1170 //release all references to the broadcaster:
1171 m_xFetchProvider.clear();
1172 m_xFetchProviderForContentAccess.clear();
1174 ContentResultSetWrapper::impl_disposing( rEventObject );
1177 //virtual
1178 void SAL_CALL CachedContentResultSet
1179 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1180 throw( RuntimeException )
1182 impl_EnsureNotDisposed();
1184 PropertyChangeEvent aEvt( rEvt );
1185 aEvt.Source = static_cast< XPropertySet * >( this );
1186 aEvt.Further = sal_False;
1187 //---------
1189 if( CCRS_PropertySetInfo
1190 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1192 //don't notify foreign events on fetchsize and fetchdirection
1193 if( aEvt.PropertyName == CCRS_PropertySetInfo
1194 ::m_aPropertyNameForFetchSize
1195 || aEvt.PropertyName == CCRS_PropertySetInfo
1196 ::m_aPropertyNameForFetchDirection )
1197 return;
1199 //adjust my props 'RowCount' and 'IsRowCountFinal'
1200 if( aEvt.PropertyName == CCRS_PropertySetInfo
1201 ::m_aPropertyNameForCount )
1202 {//RowCount changed
1204 //check value
1205 sal_Int32 nNew = 0;
1206 if( !( aEvt.NewValue >>= nNew ) )
1208 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1209 return;
1212 impl_changeRowCount( m_nKnownCount, nNew );
1214 else if( aEvt.PropertyName == CCRS_PropertySetInfo
1215 ::m_aPropertyNameForFinalCount )
1216 {//IsRowCountFinal changed
1218 //check value
1219 sal_Bool bNew = sal_False;
1220 if( !( aEvt.NewValue >>= bNew ) )
1222 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1223 return;
1225 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1227 return;
1230 //-----------
1231 impl_notifyPropertyChangeListeners( aEvt );
1235 //virtual
1236 void SAL_CALL CachedContentResultSet
1237 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1238 throw( PropertyVetoException,
1239 RuntimeException )
1241 impl_EnsureNotDisposed();
1243 //don't notify events on my properties, cause they are not vetoable
1244 if( CCRS_PropertySetInfo
1245 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1247 return;
1251 PropertyChangeEvent aEvt( rEvt );
1252 aEvt.Source = static_cast< XPropertySet * >( this );
1253 aEvt.Further = sal_False;
1255 impl_notifyVetoableChangeListeners( aEvt );
1258 //--------------------------------------------------------------------------
1259 // XContentAccess methods. ( inherited ) ( -- position dependent )
1260 //--------------------------------------------------------------------------
1262 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1263 impl_EnsureNotDisposed(); \
1264 ReacquireableGuard aGuard( m_aMutex ); \
1265 sal_Int32 nRow = m_nRow; \
1266 sal_Int32 nFetchSize = m_nFetchSize; \
1267 sal_Int32 nFetchDirection = m_nFetchDirection; \
1268 if( !m_aCache##XXX.hasRow( nRow ) ) \
1270 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1272 if( !m_xFetchProviderForContentAccess.is() ) \
1274 OSL_ENSURE( sal_False, "broadcaster was disposed already" );\
1275 throw RuntimeException(); \
1277 aGuard.clear(); \
1278 if( impl_isForwardOnly() ) \
1279 applyPositionToOrigin( nRow ); \
1281 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1283 aGuard.reacquire(); \
1284 if( !m_aCache##XXX.hasRow( nRow ) ) \
1286 aGuard.clear(); \
1287 applyPositionToOrigin( nRow ); \
1288 TYPE aRet = ContentResultSetWrapper::queryXXX(); \
1289 if( m_xContentIdentifierMapping.is() ) \
1290 return m_xContentIdentifierMapping->map##XXX( aRet );\
1291 return aRet; \
1294 return m_aCache##XXX.get##XXX( nRow );
1296 //--------------------------------------------------------------------------
1297 // virtual
1298 OUString SAL_CALL CachedContentResultSet
1299 ::queryContentIdentifierString()
1300 throw( RuntimeException )
1302 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1305 //--------------------------------------------------------------------------
1306 // virtual
1307 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1308 ::queryContentIdentifier()
1309 throw( RuntimeException )
1311 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1314 //--------------------------------------------------------------------------
1315 // virtual
1316 Reference< XContent > SAL_CALL CachedContentResultSet
1317 ::queryContent()
1318 throw( RuntimeException )
1320 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1323 //-----------------------------------------------------------------
1324 // XResultSet methods. ( inherited )
1325 //-----------------------------------------------------------------
1326 //virtual
1328 sal_Bool SAL_CALL CachedContentResultSet
1329 ::next()
1330 throw( SQLException,
1331 RuntimeException )
1333 impl_EnsureNotDisposed();
1335 ReacquireableGuard aGuard( m_aMutex );
1336 //after last
1337 if( m_bAfterLast )
1338 return sal_False;
1339 //last
1340 aGuard.clear();
1341 if( isLast() )
1343 aGuard.reacquire();
1344 m_nRow++;
1345 m_bAfterLast = sal_True;
1346 return sal_False;
1348 aGuard.reacquire();
1349 //known valid position
1350 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1352 m_nRow++;
1353 return sal_True;
1356 //unknown position
1357 sal_Int32 nRow = m_nRow;
1358 aGuard.clear();
1360 sal_Bool bValid = applyPositionToOrigin( nRow + 1 );
1362 aGuard.reacquire();
1363 m_nRow = nRow + 1;
1364 m_bAfterLast = !bValid;
1365 return bValid;
1368 //virtual
1369 sal_Bool SAL_CALL CachedContentResultSet
1370 ::previous()
1371 throw( SQLException,
1372 RuntimeException )
1374 impl_EnsureNotDisposed();
1376 if( impl_isForwardOnly() )
1377 throw SQLException();
1379 ReacquireableGuard aGuard( m_aMutex );
1380 //before first ?:
1381 if( !m_bAfterLast && !m_nRow )
1382 return sal_False;
1383 //first ?:
1384 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1386 m_nRow--;
1387 m_bAfterLast = sal_False;
1388 return sal_False;
1390 //known valid position ?:
1391 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1393 m_nRow--;
1394 m_bAfterLast = sal_False;
1395 return sal_True;
1397 //unknown position:
1398 sal_Int32 nRow = m_nRow;
1399 aGuard.clear();
1401 sal_Bool bValid = applyPositionToOrigin( nRow - 1 );
1403 aGuard.reacquire();
1404 m_nRow = nRow - 1;
1405 m_bAfterLast = sal_False;
1406 return bValid;
1409 //virtual
1410 sal_Bool SAL_CALL CachedContentResultSet
1411 ::absolute( sal_Int32 row )
1412 throw( SQLException,
1413 RuntimeException )
1415 impl_EnsureNotDisposed();
1417 if( !row )
1418 throw SQLException();
1420 if( impl_isForwardOnly() )
1421 throw SQLException();
1423 ReacquireableGuard aGuard( m_aMutex );
1425 if( !m_xResultSetOrigin.is() )
1427 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1428 return sal_False;
1430 if( row < 0 )
1432 if( m_bFinalCount )
1434 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1435 sal_Bool bValid = sal_True;
1436 if( nNewRow <= 0 )
1438 nNewRow = 0;
1439 bValid = sal_False;
1441 m_nRow = nNewRow;
1442 m_bAfterLast = sal_False;
1443 return bValid;
1445 //unknown final count:
1446 aGuard.clear();
1448 // Solaris has problems catching or propagating derived exceptions
1449 // when only the base class is known, so make ResultSetException
1450 // (derived from SQLException) known here:
1451 sal_Bool bValid;
1454 bValid = m_xResultSetOrigin->absolute( row );
1456 catch (ResultSetException &)
1458 throw;
1461 aGuard.reacquire();
1462 if( m_bFinalCount )
1464 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1465 if( nNewRow < 0 )
1466 nNewRow = 0;
1467 m_nLastAppliedPos = nNewRow;
1468 m_nRow = nNewRow;
1469 m_bAfterLastApplied = m_bAfterLast = sal_False;
1470 return bValid;
1472 aGuard.clear();
1474 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1476 aGuard.reacquire();
1477 m_nLastAppliedPos = nCurRow;
1478 m_nRow = nCurRow;
1479 m_bAfterLast = sal_False;
1480 return nCurRow != 0;
1482 //row > 0:
1483 if( m_bFinalCount )
1485 if( row > m_nKnownCount )
1487 m_nRow = m_nKnownCount + 1;
1488 m_bAfterLast = sal_True;
1489 return sal_False;
1491 m_nRow = row;
1492 m_bAfterLast = sal_False;
1493 return sal_True;
1495 //unknown new position:
1496 aGuard.clear();
1498 sal_Bool bValid = m_xResultSetOrigin->absolute( row );
1500 aGuard.reacquire();
1501 if( m_bFinalCount )
1503 sal_Int32 nNewRow = row;
1504 if( nNewRow > m_nKnownCount )
1506 nNewRow = m_nKnownCount + 1;
1507 m_bAfterLastApplied = m_bAfterLast = sal_True;
1509 else
1510 m_bAfterLastApplied = m_bAfterLast = sal_False;
1512 m_nLastAppliedPos = nNewRow;
1513 m_nRow = nNewRow;
1514 return bValid;
1516 aGuard.clear();
1518 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1519 sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1521 aGuard.reacquire();
1522 m_nLastAppliedPos = nCurRow;
1523 m_nRow = nCurRow;
1524 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1525 return nCurRow && !bIsAfterLast;
1528 //virtual
1529 sal_Bool SAL_CALL CachedContentResultSet
1530 ::relative( sal_Int32 rows )
1531 throw( SQLException,
1532 RuntimeException )
1534 impl_EnsureNotDisposed();
1536 if( impl_isForwardOnly() )
1537 throw SQLException();
1539 ReacquireableGuard aGuard( m_aMutex );
1540 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1541 throw SQLException();
1543 if( !rows )
1544 return sal_True;
1546 sal_Int32 nNewRow = m_nRow + rows;
1547 if( nNewRow < 0 )
1548 nNewRow = 0;
1550 if( impl_isKnownValidPosition( nNewRow ) )
1552 m_nRow = nNewRow;
1553 m_bAfterLast = sal_False;
1554 return sal_True;
1556 else
1558 //known invalid new position:
1559 if( nNewRow == 0 )
1561 m_bAfterLast = sal_False;
1562 m_nRow = 0;
1563 return sal_False;
1565 if( m_bFinalCount && nNewRow > m_nKnownCount )
1567 m_bAfterLast = sal_True;
1568 m_nRow = m_nKnownCount + 1;
1569 return sal_False;
1571 //unknown new position:
1572 aGuard.clear();
1573 sal_Bool bValid = applyPositionToOrigin( nNewRow );
1575 aGuard.reacquire();
1576 m_nRow = nNewRow;
1577 m_bAfterLast = !bValid && nNewRow > 0;
1578 return bValid;
1583 //virtual
1584 sal_Bool SAL_CALL CachedContentResultSet
1585 ::first()
1586 throw( SQLException,
1587 RuntimeException )
1589 impl_EnsureNotDisposed();
1591 if( impl_isForwardOnly() )
1592 throw SQLException();
1594 ReacquireableGuard aGuard( m_aMutex );
1595 if( impl_isKnownValidPosition( 1 ) )
1597 m_nRow = 1;
1598 m_bAfterLast = sal_False;
1599 return sal_True;
1601 if( impl_isKnownInvalidPosition( 1 ) )
1603 m_nRow = 1;
1604 m_bAfterLast = sal_False;
1605 return sal_False;
1607 //unknown position
1608 aGuard.clear();
1610 sal_Bool bValid = applyPositionToOrigin( 1 );
1612 aGuard.reacquire();
1613 m_nRow = 1;
1614 m_bAfterLast = sal_False;
1615 return bValid;
1618 //virtual
1619 sal_Bool SAL_CALL CachedContentResultSet
1620 ::last()
1621 throw( SQLException,
1622 RuntimeException )
1624 impl_EnsureNotDisposed();
1626 if( impl_isForwardOnly() )
1627 throw SQLException();
1629 ReacquireableGuard aGuard( m_aMutex );
1630 if( m_bFinalCount )
1632 m_nRow = m_nKnownCount;
1633 m_bAfterLast = sal_False;
1634 return m_nKnownCount != 0;
1636 //unknown position
1637 if( !m_xResultSetOrigin.is() )
1639 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1640 return sal_False;
1642 aGuard.clear();
1644 sal_Bool bValid = m_xResultSetOrigin->last();
1646 aGuard.reacquire();
1647 m_bAfterLastApplied = m_bAfterLast = sal_False;
1648 if( m_bFinalCount )
1650 m_nLastAppliedPos = m_nKnownCount;
1651 m_nRow = m_nKnownCount;
1652 return bValid;
1654 aGuard.clear();
1656 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1658 aGuard.reacquire();
1659 m_nLastAppliedPos = nCurRow;
1660 m_nRow = nCurRow;
1661 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1662 m_nKnownCount = nCurRow;
1663 m_bFinalCount = sal_True;
1664 return nCurRow != 0;
1667 //virtual
1668 void SAL_CALL CachedContentResultSet
1669 ::beforeFirst()
1670 throw( SQLException,
1671 RuntimeException )
1673 impl_EnsureNotDisposed();
1675 if( impl_isForwardOnly() )
1676 throw SQLException();
1678 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1679 m_nRow = 0;
1680 m_bAfterLast = sal_False;
1683 //virtual
1684 void SAL_CALL CachedContentResultSet
1685 ::afterLast()
1686 throw( SQLException,
1687 RuntimeException )
1689 impl_EnsureNotDisposed();
1691 if( impl_isForwardOnly() )
1692 throw SQLException();
1694 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1695 m_nRow = 1;
1696 m_bAfterLast = sal_True;
1699 //virtual
1700 sal_Bool SAL_CALL CachedContentResultSet
1701 ::isAfterLast()
1702 throw( SQLException,
1703 RuntimeException )
1705 impl_EnsureNotDisposed();
1707 ReacquireableGuard aGuard( m_aMutex );
1708 if( !m_bAfterLast )
1709 return sal_False;
1710 if( m_nKnownCount )
1711 return m_bAfterLast;
1712 if( m_bFinalCount )
1713 return sal_False;
1715 if( !m_xResultSetOrigin.is() )
1717 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1718 return sal_False;
1720 aGuard.clear();
1722 //find out whethter the original resultset contains rows or not
1723 m_xResultSetOrigin->afterLast();
1725 aGuard.reacquire();
1726 m_bAfterLastApplied = sal_True;
1727 aGuard.clear();
1729 return m_xResultSetOrigin->isAfterLast();
1732 //virtual
1733 sal_Bool SAL_CALL CachedContentResultSet
1734 ::isBeforeFirst()
1735 throw( SQLException,
1736 RuntimeException )
1738 impl_EnsureNotDisposed();
1740 ReacquireableGuard aGuard( m_aMutex );
1741 if( m_bAfterLast )
1742 return sal_False;
1743 if( m_nRow )
1744 return sal_False;
1745 if( m_nKnownCount )
1746 return !m_nRow;
1747 if( m_bFinalCount )
1748 return sal_False;
1750 if( !m_xResultSetOrigin.is() )
1752 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1753 return sal_False;
1755 aGuard.clear();
1757 //find out whethter the original resultset contains rows or not
1758 m_xResultSetOrigin->beforeFirst();
1760 aGuard.reacquire();
1761 m_bAfterLastApplied = sal_False;
1762 m_nLastAppliedPos = 0;
1763 aGuard.clear();
1765 return m_xResultSetOrigin->isBeforeFirst();
1768 //virtual
1769 sal_Bool SAL_CALL CachedContentResultSet
1770 ::isFirst()
1771 throw( SQLException,
1772 RuntimeException )
1774 impl_EnsureNotDisposed();
1776 sal_Int32 nRow = 0;
1777 Reference< XResultSet > xResultSetOrigin;
1780 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1781 if( m_bAfterLast )
1782 return sal_False;
1783 if( m_nRow != 1 )
1784 return sal_False;
1785 if( m_nKnownCount )
1786 return m_nRow == 1;
1787 if( m_bFinalCount )
1788 return sal_False;
1790 nRow = m_nRow;
1791 xResultSetOrigin = m_xResultSetOrigin;
1794 //need to ask origin
1796 if( applyPositionToOrigin( nRow ) )
1797 return xResultSetOrigin->isFirst();
1798 else
1799 return sal_False;
1803 //virtual
1804 sal_Bool SAL_CALL CachedContentResultSet
1805 ::isLast()
1806 throw( SQLException,
1807 RuntimeException )
1809 impl_EnsureNotDisposed();
1811 sal_Int32 nRow = 0;
1812 Reference< XResultSet > xResultSetOrigin;
1814 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1815 if( m_bAfterLast )
1816 return sal_False;
1817 if( m_nRow < m_nKnownCount )
1818 return sal_False;
1819 if( m_bFinalCount )
1820 return m_nKnownCount && m_nRow == m_nKnownCount;
1822 nRow = m_nRow;
1823 xResultSetOrigin = m_xResultSetOrigin;
1826 //need to ask origin
1828 if( applyPositionToOrigin( nRow ) )
1829 return xResultSetOrigin->isLast();
1830 else
1831 return sal_False;
1836 //virtual
1837 sal_Int32 SAL_CALL CachedContentResultSet
1838 ::getRow()
1839 throw( SQLException,
1840 RuntimeException )
1842 impl_EnsureNotDisposed();
1844 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1845 if( m_bAfterLast )
1846 return 0;
1847 return m_nRow;
1850 //virtual
1851 void SAL_CALL CachedContentResultSet
1852 ::refreshRow()
1853 throw( SQLException,
1854 RuntimeException )
1856 impl_EnsureNotDisposed();
1858 //the ContentResultSet is static and will not change
1859 //therefore we don't need to reload anything
1862 //virtual
1863 sal_Bool SAL_CALL CachedContentResultSet
1864 ::rowUpdated()
1865 throw( SQLException,
1866 RuntimeException )
1868 impl_EnsureNotDisposed();
1870 //the ContentResultSet is static and will not change
1871 return sal_False;
1873 //virtual
1874 sal_Bool SAL_CALL CachedContentResultSet
1875 ::rowInserted()
1876 throw( SQLException,
1877 RuntimeException )
1879 impl_EnsureNotDisposed();
1881 //the ContentResultSet is static and will not change
1882 return sal_False;
1885 //virtual
1886 sal_Bool SAL_CALL CachedContentResultSet
1887 ::rowDeleted()
1888 throw( SQLException,
1889 RuntimeException )
1891 impl_EnsureNotDisposed();
1893 //the ContentResultSet is static and will not change
1894 return sal_False;
1897 //virtual
1898 Reference< XInterface > SAL_CALL CachedContentResultSet
1899 ::getStatement()
1900 throw( SQLException,
1901 RuntimeException )
1903 impl_EnsureNotDisposed();
1904 //@todo ?return anything
1905 return Reference< XInterface >();
1908 //-----------------------------------------------------------------
1909 // XRow methods. ( inherited )
1910 //-----------------------------------------------------------------
1912 //virtual
1913 sal_Bool SAL_CALL CachedContentResultSet
1914 ::wasNull()
1915 throw( SQLException,
1916 RuntimeException )
1918 impl_EnsureNotDisposed();
1919 impl_init_xRowOrigin();
1921 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1922 if( m_bLastReadWasFromCache )
1923 return m_bLastCachedReadWasNull;
1924 if( !m_xRowOrigin.is() )
1926 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1927 return sal_False;
1930 return m_xRowOrigin->wasNull();
1933 //virtual
1934 rtl::OUString SAL_CALL CachedContentResultSet
1935 ::getString( sal_Int32 columnIndex )
1936 throw( SQLException,
1937 RuntimeException )
1939 XROW_GETXXX( getString, OUString );
1942 //virtual
1943 sal_Bool SAL_CALL CachedContentResultSet
1944 ::getBoolean( sal_Int32 columnIndex )
1945 throw( SQLException,
1946 RuntimeException )
1948 XROW_GETXXX( getBoolean, sal_Bool );
1951 //virtual
1952 sal_Int8 SAL_CALL CachedContentResultSet
1953 ::getByte( sal_Int32 columnIndex )
1954 throw( SQLException,
1955 RuntimeException )
1957 XROW_GETXXX( getByte, sal_Int8 );
1960 //virtual
1961 sal_Int16 SAL_CALL CachedContentResultSet
1962 ::getShort( sal_Int32 columnIndex )
1963 throw( SQLException,
1964 RuntimeException )
1966 XROW_GETXXX( getShort, sal_Int16 );
1969 //virtual
1970 sal_Int32 SAL_CALL CachedContentResultSet
1971 ::getInt( sal_Int32 columnIndex )
1972 throw( SQLException,
1973 RuntimeException )
1975 XROW_GETXXX( getInt, sal_Int32 );
1978 //virtual
1979 sal_Int64 SAL_CALL CachedContentResultSet
1980 ::getLong( sal_Int32 columnIndex )
1981 throw( SQLException,
1982 RuntimeException )
1984 XROW_GETXXX( getLong, sal_Int64 );
1987 //virtual
1988 float SAL_CALL CachedContentResultSet
1989 ::getFloat( sal_Int32 columnIndex )
1990 throw( SQLException,
1991 RuntimeException )
1993 XROW_GETXXX( getFloat, float );
1996 //virtual
1997 double SAL_CALL CachedContentResultSet
1998 ::getDouble( sal_Int32 columnIndex )
1999 throw( SQLException,
2000 RuntimeException )
2002 XROW_GETXXX( getDouble, double );
2005 //virtual
2006 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
2007 ::getBytes( sal_Int32 columnIndex )
2008 throw( SQLException,
2009 RuntimeException )
2011 XROW_GETXXX( getBytes, Sequence< sal_Int8 > );
2014 //virtual
2015 Date SAL_CALL CachedContentResultSet
2016 ::getDate( sal_Int32 columnIndex )
2017 throw( SQLException,
2018 RuntimeException )
2020 XROW_GETXXX( getDate, Date );
2023 //virtual
2024 Time SAL_CALL CachedContentResultSet
2025 ::getTime( sal_Int32 columnIndex )
2026 throw( SQLException,
2027 RuntimeException )
2029 XROW_GETXXX( getTime, Time );
2032 //virtual
2033 DateTime SAL_CALL CachedContentResultSet
2034 ::getTimestamp( sal_Int32 columnIndex )
2035 throw( SQLException,
2036 RuntimeException )
2038 XROW_GETXXX( getTimestamp, DateTime );
2041 //virtual
2042 Reference< com::sun::star::io::XInputStream >
2043 SAL_CALL CachedContentResultSet
2044 ::getBinaryStream( sal_Int32 columnIndex )
2045 throw( SQLException,
2046 RuntimeException )
2048 XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > );
2051 //virtual
2052 Reference< com::sun::star::io::XInputStream >
2053 SAL_CALL CachedContentResultSet
2054 ::getCharacterStream( sal_Int32 columnIndex )
2055 throw( SQLException,
2056 RuntimeException )
2058 XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > );
2061 //virtual
2062 Any SAL_CALL CachedContentResultSet
2063 ::getObject( sal_Int32 columnIndex,
2064 const Reference<
2065 com::sun::star::container::XNameAccess >& typeMap )
2066 throw( SQLException,
2067 RuntimeException )
2069 //if you change this macro please pay attention to
2070 //define XROW_GETXXX, where this is similar implemented
2072 ReacquireableGuard aGuard( m_aMutex );
2073 sal_Int32 nRow = m_nRow;
2074 sal_Int32 nFetchSize = m_nFetchSize;
2075 sal_Int32 nFetchDirection = m_nFetchDirection;
2076 if( !m_aCache.hasRow( nRow ) )
2078 if( !m_aCache.hasCausedException( nRow ) )
2080 if( !m_xFetchProvider.is() )
2082 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
2083 return Any();
2085 aGuard.clear();
2087 impl_fetchData( nRow, nFetchSize, nFetchDirection );
2089 aGuard.reacquire();
2090 if( !m_aCache.hasRow( nRow ) )
2092 m_bLastReadWasFromCache = sal_False;
2093 aGuard.clear();
2094 applyPositionToOrigin( nRow );
2095 impl_init_xRowOrigin();
2096 return m_xRowOrigin->getObject( columnIndex, typeMap );
2099 //@todo: pay attention to typeMap
2100 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2101 Any aRet;
2102 m_bLastReadWasFromCache = sal_True;
2103 m_bLastCachedReadWasNull = !( rValue >>= aRet );
2104 return aRet;
2107 //virtual
2108 Reference< XRef > SAL_CALL CachedContentResultSet
2109 ::getRef( sal_Int32 columnIndex )
2110 throw( SQLException,
2111 RuntimeException )
2113 XROW_GETXXX( getRef, Reference< XRef > );
2116 //virtual
2117 Reference< XBlob > SAL_CALL CachedContentResultSet
2118 ::getBlob( sal_Int32 columnIndex )
2119 throw( SQLException,
2120 RuntimeException )
2122 XROW_GETXXX( getBlob, Reference< XBlob > );
2125 //virtual
2126 Reference< XClob > SAL_CALL CachedContentResultSet
2127 ::getClob( sal_Int32 columnIndex )
2128 throw( SQLException,
2129 RuntimeException )
2131 XROW_GETXXX( getClob, Reference< XClob > );
2134 //virtual
2135 Reference< XArray > SAL_CALL CachedContentResultSet
2136 ::getArray( sal_Int32 columnIndex )
2137 throw( SQLException,
2138 RuntimeException )
2140 XROW_GETXXX( getArray, Reference< XArray > );
2143 //-----------------------------------------------------------------
2144 // Type Converter Support
2145 //-----------------------------------------------------------------
2147 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2149 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2151 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2153 m_bTriedToGetTypeConverter = sal_True;
2154 m_xTypeConverter = Reference< XTypeConverter >(
2155 m_xSMgr->createInstance(
2156 OUString::createFromAscii(
2157 "com.sun.star.script.Converter" ) ),
2158 UNO_QUERY );
2160 OSL_ENSURE( m_xTypeConverter.is(),
2161 "PropertyValueSet::getTypeConverter() - "
2162 "Service 'com.sun.star.script.Converter' n/a!" );
2164 return m_xTypeConverter;
2167 //--------------------------------------------------------------------------
2168 //--------------------------------------------------------------------------
2169 // class CachedContentResultSetFactory
2170 //--------------------------------------------------------------------------
2171 //--------------------------------------------------------------------------
2173 CachedContentResultSetFactory::CachedContentResultSetFactory(
2174 const Reference< XMultiServiceFactory > & rSMgr )
2176 m_xSMgr = rSMgr;
2179 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2183 //--------------------------------------------------------------------------
2184 // CachedContentResultSetFactory XInterface methods.
2185 //--------------------------------------------------------------------------
2187 XINTERFACE_IMPL_3( CachedContentResultSetFactory,
2188 XTypeProvider,
2189 XServiceInfo,
2190 XCachedContentResultSetFactory );
2192 //--------------------------------------------------------------------------
2193 // CachedContentResultSetFactory XTypeProvider methods.
2194 //--------------------------------------------------------------------------
2196 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2197 XTypeProvider,
2198 XServiceInfo,
2199 XCachedContentResultSetFactory );
2201 //--------------------------------------------------------------------------
2202 // CachedContentResultSetFactory XServiceInfo methods.
2203 //--------------------------------------------------------------------------
2205 XSERVICEINFO_IMPL_1( CachedContentResultSetFactory,
2206 OUString::createFromAscii(
2207 "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2208 OUString::createFromAscii(
2209 CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2211 //--------------------------------------------------------------------------
2212 // Service factory implementation.
2213 //--------------------------------------------------------------------------
2215 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2217 //--------------------------------------------------------------------------
2218 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2219 //--------------------------------------------------------------------------
2221 //virtual
2222 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2223 ::createCachedContentResultSet(
2224 const Reference< XResultSet > & xSource,
2225 const Reference< XContentIdentifierMapping > & xMapping )
2226 throw( com::sun::star::uno::RuntimeException )
2228 Reference< XResultSet > xRet;
2229 xRet = new CachedContentResultSet( m_xSMgr, xSource, xMapping );
2230 return xRet;