bump product version to 4.1.6.2
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blob52e7d2f9dd55057a13c0222d22204ccce825317b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cachedcontentresultset.hxx>
22 #include <com/sun/star/sdbc/FetchDirection.hpp>
23 #include <com/sun/star/ucb/FetchError.hpp>
24 #include <com/sun/star/ucb/ResultSetException.hpp>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/script/Converter.hpp>
27 #include <com/sun/star/sdbc/ResultSetType.hpp>
28 #include <rtl/ustring.hxx>
29 #include <osl/diagnose.h>
30 #include <comphelper/processfactory.hxx>
32 using namespace com::sun::star::beans;
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::script;
35 using namespace com::sun::star::sdbc;
36 using namespace com::sun::star::ucb;
37 using namespace com::sun::star::uno;
38 using namespace com::sun::star::util;
39 using namespace cppu;
42 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
43 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
45 //--------------------------------------------------------------------------
46 //--------------------------------------------------------------------------
47 //define for getXXX methods of interface XRow
48 //--------------------------------------------------------------------------
49 //--------------------------------------------------------------------------
51 //if you change this macro please pay attention to
52 //function ::getObject, where this is similar implemented
54 #define XROW_GETXXX( getXXX, Type ) \
55 impl_EnsureNotDisposed(); \
56 ReacquireableGuard aGuard( m_aMutex ); \
57 sal_Int32 nRow = m_nRow; \
58 sal_Int32 nFetchSize = m_nFetchSize; \
59 sal_Int32 nFetchDirection = m_nFetchDirection; \
60 if( !m_aCache.hasRow( nRow ) ) \
61 { \
62 if( !m_aCache.hasCausedException( nRow ) ) \
63 { \
64 if( !m_xFetchProvider.is() ) \
65 { \
66 OSL_FAIL( "broadcaster was disposed already" ); \
67 throw SQLException(); \
68 } \
69 aGuard.clear(); \
70 if( impl_isForwardOnly() ) \
71 applyPositionToOrigin( nRow ); \
73 impl_fetchData( nRow, nFetchSize, nFetchDirection ); \
74 } \
75 aGuard.reacquire(); \
76 if( !m_aCache.hasRow( nRow ) ) \
77 { \
78 m_bLastReadWasFromCache = sal_False; \
79 aGuard.clear(); \
80 applyPositionToOrigin( nRow ); \
81 impl_init_xRowOrigin(); \
82 return m_xRowOrigin->getXXX( columnIndex ); \
83 } \
84 } \
85 const Any& rValue = m_aCache.getAny( nRow, columnIndex );\
86 Type aRet = Type(); \
87 m_bLastReadWasFromCache = sal_True; \
88 m_bLastCachedReadWasNull = !( rValue >>= aRet ); \
89 /* Last chance. Try type converter service... */ \
90 if ( m_bLastCachedReadWasNull && rValue.hasValue() ) \
91 { \
92 Reference< XTypeConverter > xConverter \
93 = getTypeConverter(); \
94 if ( xConverter.is() ) \
95 { \
96 try \
97 { \
98 Any aConvAny = xConverter->convertTo( \
99 rValue, \
100 getCppuType( static_cast< \
101 const Type * >( 0 ) ) ); \
102 m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \
104 catch (const IllegalArgumentException&) \
107 catch (const CannotConvertException&) \
112 return aRet;
114 //--------------------------------------------------------------------------
115 //--------------------------------------------------------------------------
116 // CCRS_Cache methoeds.
117 //--------------------------------------------------------------------------
118 //--------------------------------------------------------------------------
120 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
121 const Reference< XContentIdentifierMapping > & xMapping )
122 : m_pResult( NULL )
123 , m_xContentIdentifierMapping( xMapping )
124 , m_pMappedReminder( NULL )
128 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
130 delete m_pResult;
133 void SAL_CALL CachedContentResultSet::CCRS_Cache
134 ::clear()
136 if( m_pResult )
138 delete m_pResult;
139 m_pResult = NULL;
141 clearMappedReminder();
144 void SAL_CALL CachedContentResultSet::CCRS_Cache
145 ::loadData( const FetchResult& rResult )
147 clear();
148 m_pResult = new FetchResult( rResult );
151 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
152 ::hasRow( sal_Int32 row )
154 if( !m_pResult )
155 return sal_False;
156 long nStart = m_pResult->StartIndex;
157 long nEnd = nStart;
158 if( m_pResult->Orientation )
159 nEnd += m_pResult->Rows.getLength() - 1;
160 else
161 nStart -= m_pResult->Rows.getLength() + 1;
163 return nStart <= row && row <= nEnd;
166 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
167 ::getMaxRow()
169 if( !m_pResult )
170 return 0;
171 long nEnd = m_pResult->StartIndex;
172 if( m_pResult->Orientation )
173 return nEnd += m_pResult->Rows.getLength() - 1;
174 else
175 return nEnd;
178 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
179 ::hasKnownLast()
181 if( !m_pResult )
182 return sal_False;
184 if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
185 && m_pResult->Orientation
186 && m_pResult->Rows.getLength() )
187 return sal_True;
189 return sal_False;
192 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
193 ::hasCausedException( sal_Int32 nRow )
195 if( !m_pResult )
196 return sal_False;
197 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
198 return sal_False;
200 long nEnd = m_pResult->StartIndex;
201 if( m_pResult->Orientation )
202 nEnd += m_pResult->Rows.getLength();
204 return nRow == nEnd+1;
207 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
208 ::getRowAny( sal_Int32 nRow )
209 throw( SQLException,
210 RuntimeException )
212 if( !nRow )
213 throw SQLException();
214 if( !m_pResult )
215 throw SQLException();
216 if( !hasRow( nRow ) )
217 throw SQLException();
219 long nDiff = nRow - m_pResult->StartIndex;
220 if( nDiff < 0 )
221 nDiff *= -1;
223 return (m_pResult->Rows)[nDiff];
226 void SAL_CALL CachedContentResultSet::CCRS_Cache
227 ::remindMapped( sal_Int32 nRow )
229 //remind that this row was mapped
230 if( !m_pResult )
231 return;
232 long nDiff = nRow - m_pResult->StartIndex;
233 if( nDiff < 0 )
234 nDiff *= -1;
235 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
236 if( nDiff < pMappedReminder->getLength() )
237 (*pMappedReminder)[nDiff] = sal_True;
240 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
241 ::isRowMapped( sal_Int32 nRow )
243 if( !m_pMappedReminder || !m_pResult )
244 return sal_False;
245 long nDiff = nRow - m_pResult->StartIndex;
246 if( nDiff < 0 )
247 nDiff *= -1;
248 if( nDiff < m_pMappedReminder->getLength() )
249 return (*m_pMappedReminder)[nDiff];
250 return sal_False;
253 void SAL_CALL CachedContentResultSet::CCRS_Cache
254 ::clearMappedReminder()
256 delete m_pMappedReminder;
257 m_pMappedReminder = NULL;
260 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
261 ::getMappedReminder()
263 if( !m_pMappedReminder )
265 sal_Int32 nCount = m_pResult->Rows.getLength();
266 m_pMappedReminder = new Sequence< sal_Bool >( nCount );
267 for( ;nCount; nCount-- )
268 (*m_pMappedReminder)[nCount] = sal_False;
270 return m_pMappedReminder;
273 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
274 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
275 throw( SQLException,
276 RuntimeException )
278 if( !nColumnIndex )
279 throw SQLException();
280 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
282 Any& rRow = getRowAny( nRow );
283 Sequence< Any > aValue;
284 rRow >>= aValue;
285 if( m_xContentIdentifierMapping->mapRow( aValue ) )
287 rRow <<= aValue;
288 remindMapped( nRow );
290 else
291 m_xContentIdentifierMapping.clear();
293 const Sequence< Any >& rRow =
294 (* reinterpret_cast< const Sequence< Any > * >
295 (getRowAny( nRow ).getValue() ));
297 if( nColumnIndex > rRow.getLength() )
298 throw SQLException();
299 return rRow[nColumnIndex-1];
302 const OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
303 ::getContentIdentifierString( sal_Int32 nRow )
304 throw( com::sun::star::uno::RuntimeException )
308 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
310 Any& rRow = getRowAny( nRow );
311 OUString aValue;
312 rRow >>= aValue;
313 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
314 remindMapped( nRow );
316 return (* reinterpret_cast< const OUString * >
317 (getRowAny( nRow ).getValue() ));
319 catch(const SQLException&)
321 throw RuntimeException();
325 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
326 ::getContentIdentifier( sal_Int32 nRow )
327 throw( com::sun::star::uno::RuntimeException )
331 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
333 Any& rRow = getRowAny( nRow );
334 Reference< XContentIdentifier > aValue;
335 rRow >>= aValue;
336 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
337 remindMapped( nRow );
339 return (* reinterpret_cast< const Reference< XContentIdentifier > * >
340 (getRowAny( nRow ).getValue() ));
342 catch(const SQLException&)
344 throw RuntimeException();
348 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
349 ::getContent( sal_Int32 nRow )
350 throw( com::sun::star::uno::RuntimeException )
354 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
356 Any& rRow = getRowAny( nRow );
357 Reference< XContent > aValue;
358 rRow >>= aValue;
359 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
360 remindMapped( nRow );
362 return (* reinterpret_cast< const Reference< XContent > * >
363 (getRowAny( nRow ).getValue() ));
365 catch (const SQLException&)
367 throw RuntimeException();
371 //--------------------------------------------------------------------------
372 //--------------------------------------------------------------------------
373 // class CCRS_PropertySetInfo
374 //--------------------------------------------------------------------------
375 //--------------------------------------------------------------------------
377 class CCRS_PropertySetInfo :
378 public cppu::OWeakObject,
379 public com::sun::star::lang::XTypeProvider,
380 public com::sun::star::beans::XPropertySetInfo
382 friend class CachedContentResultSet;
384 //my Properties
385 Sequence< com::sun::star::beans::Property >*
386 m_pProperties;
388 //some helping variables ( names for my special properties )
389 static OUString m_aPropertyNameForCount;
390 static OUString m_aPropertyNameForFinalCount;
391 static OUString m_aPropertyNameForFetchSize;
392 static OUString m_aPropertyNameForFetchDirection;
394 long m_nFetchSizePropertyHandle;
395 long m_nFetchDirectionPropertyHandle;
397 private:
398 sal_Int32 SAL_CALL
399 impl_getRemainedHandle() const;
401 sal_Bool SAL_CALL
402 impl_queryProperty(
403 const OUString& rName
404 , com::sun::star::beans::Property& rProp ) const;
405 sal_Int32 SAL_CALL
406 impl_getPos( const OUString& rName ) const;
408 static sal_Bool SAL_CALL
409 impl_isMyPropertyName( const OUString& rName );
411 public:
412 CCRS_PropertySetInfo( Reference<
413 XPropertySetInfo > xPropertySetInfoOrigin );
415 virtual ~CCRS_PropertySetInfo();
417 // XInterface
418 XINTERFACE_DECL()
420 // XTypeProvider
421 XTYPEPROVIDER_DECL()
423 // XPropertySetInfo
424 virtual Sequence< com::sun::star::beans::Property > SAL_CALL
425 getProperties()
426 throw( RuntimeException );
428 virtual com::sun::star::beans::Property SAL_CALL
429 getPropertyByName( const OUString& aName )
430 throw( com::sun::star::beans::UnknownPropertyException, RuntimeException );
432 virtual sal_Bool SAL_CALL
433 hasPropertyByName( const OUString& Name )
434 throw( RuntimeException );
437 OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( "RowCount" );
438 OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( "IsRowCountFinal" );
439 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( "FetchSize" );
440 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( "FetchDirection" );
442 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
443 Reference< XPropertySetInfo > xInfo )
444 : m_pProperties( NULL )
445 , m_nFetchSizePropertyHandle( -1 )
446 , m_nFetchDirectionPropertyHandle( -1 )
448 //initialize list of properties:
450 // it is required, that the received xInfo contains the two
451 // properties with names 'm_aPropertyNameForCount' and
452 // 'm_aPropertyNameForFinalCount'
454 if( xInfo.is() )
456 Sequence<Property> aProps = xInfo->getProperties();
457 m_pProperties = new Sequence<Property> ( aProps );
459 else
461 OSL_FAIL( "The received XPropertySetInfo doesn't contain required properties" );
462 m_pProperties = new Sequence<Property>;
465 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
466 sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
467 sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
468 sal_Int32 nDeleted = 0;
469 if( nFetchSize != -1 )
470 nDeleted++;
471 if( nFetchDirection != -1 )
472 nDeleted++;
474 Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
475 sal_Int32 nOrigProps = pOrigProps->getLength();
477 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
478 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
480 if( n == nFetchSize || n == nFetchDirection )
481 m--;
482 else
483 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
486 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
487 rMyProp.Name = m_aPropertyNameForFetchSize;
488 rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) );
489 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
491 if( nFetchSize != -1 )
492 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
493 else
494 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
496 rMyProp.Handle = m_nFetchSizePropertyHandle;
500 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
501 rMyProp.Name = m_aPropertyNameForFetchDirection;
502 rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) );
503 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
505 if( nFetchDirection != -1 )
506 m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
507 else
508 m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
510 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
512 delete pOrigProps;
515 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
517 delete m_pProperties;
520 //--------------------------------------------------------------------------
521 // XInterface methods.
522 //--------------------------------------------------------------------------
523 //list all interfaces inclusive baseclasses of interfaces
524 XINTERFACE_IMPL_2( CCRS_PropertySetInfo
525 , XTypeProvider
526 , XPropertySetInfo
529 //--------------------------------------------------------------------------
530 // XTypeProvider methods.
531 //--------------------------------------------------------------------------
532 //list all interfaces exclusive baseclasses
533 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
534 , XTypeProvider
535 , XPropertySetInfo
537 //--------------------------------------------------------------------------
538 // XPropertySetInfo methods.
539 //--------------------------------------------------------------------------
540 //virtual
541 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
542 ::getProperties() throw( RuntimeException )
544 return *m_pProperties;
547 //virtual
548 Property SAL_CALL CCRS_PropertySetInfo
549 ::getPropertyByName( const OUString& aName )
550 throw( UnknownPropertyException, RuntimeException )
552 if ( aName.isEmpty() )
553 throw UnknownPropertyException();
555 Property aProp;
556 if ( impl_queryProperty( aName, aProp ) )
557 return aProp;
559 throw UnknownPropertyException();
562 //virtual
563 sal_Bool SAL_CALL CCRS_PropertySetInfo
564 ::hasPropertyByName( const OUString& Name )
565 throw( RuntimeException )
567 return ( impl_getPos( Name ) != -1 );
570 //--------------------------------------------------------------------------
571 // impl_ methods.
572 //--------------------------------------------------------------------------
574 sal_Int32 SAL_CALL CCRS_PropertySetInfo
575 ::impl_getPos( const OUString& rName ) const
577 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
579 const Property& rMyProp = (*m_pProperties)[nN];
580 if( rMyProp.Name == rName )
581 return nN;
583 return -1;
586 sal_Bool SAL_CALL CCRS_PropertySetInfo
587 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
589 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
591 const Property& rMyProp = (*m_pProperties)[nN];
592 if( rMyProp.Name == rName )
594 rProp.Name = rMyProp.Name;
595 rProp.Handle = rMyProp.Handle;
596 rProp.Type = rMyProp.Type;
597 rProp.Attributes = rMyProp.Attributes;
599 return sal_True;
602 return sal_False;
605 //static
606 sal_Bool SAL_CALL CCRS_PropertySetInfo
607 ::impl_isMyPropertyName( const OUString& rPropertyName )
609 return ( rPropertyName == m_aPropertyNameForCount
610 || rPropertyName == m_aPropertyNameForFinalCount
611 || rPropertyName == m_aPropertyNameForFetchSize
612 || rPropertyName == m_aPropertyNameForFetchDirection );
615 sal_Int32 SAL_CALL CCRS_PropertySetInfo
616 ::impl_getRemainedHandle( ) const
618 sal_Int32 nHandle = 1;
620 if( !m_pProperties )
622 OSL_FAIL( "Properties not initialized yet" );
623 return nHandle;
625 sal_Bool bFound = sal_True;
626 while( bFound )
628 bFound = sal_False;
629 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
631 if( nHandle == (*m_pProperties)[nN].Handle )
633 bFound = sal_True;
634 nHandle++;
635 break;
639 return nHandle;
642 //--------------------------------------------------------------------------
643 //--------------------------------------------------------------------------
644 // class CachedContentResultSet
645 //--------------------------------------------------------------------------
646 //--------------------------------------------------------------------------
648 CachedContentResultSet::CachedContentResultSet(
649 const Reference< XComponentContext > & rxContext
650 , const Reference< XResultSet > & xOrigin
651 , const Reference< XContentIdentifierMapping > &
652 xContentIdentifierMapping )
653 : ContentResultSetWrapper( xOrigin )
655 , m_xContext( rxContext )
656 , m_xFetchProvider( NULL )
657 , m_xFetchProviderForContentAccess( NULL )
659 , m_xMyPropertySetInfo( NULL )
660 , m_pMyPropSetInfo( NULL )
662 , m_xContentIdentifierMapping( xContentIdentifierMapping )
663 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
664 , m_bAfterLast( sal_False )
665 , m_nLastAppliedPos( 0 )
666 , m_bAfterLastApplied( sal_False )
667 , m_nKnownCount( 0 )
668 , m_bFinalCount( sal_False )
669 , m_nFetchSize(
670 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
671 , m_nFetchDirection(
672 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
674 , m_bLastReadWasFromCache( sal_False )
675 , m_bLastCachedReadWasNull( sal_True )
676 , m_aCache( m_xContentIdentifierMapping )
677 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
678 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
679 , m_aCacheContent( m_xContentIdentifierMapping )
680 , m_bTriedToGetTypeConverter( sal_False )
681 , m_xTypeConverter( NULL )
683 m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
684 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
686 m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
687 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
689 impl_init();
692 CachedContentResultSet::~CachedContentResultSet()
694 impl_deinit();
695 //do not delete m_pMyPropSetInfo, cause it is hold via reference
698 //--------------------------------------------------------------------------
699 // impl_ methods.
700 //--------------------------------------------------------------------------
702 sal_Bool SAL_CALL CachedContentResultSet
703 ::applyPositionToOrigin( sal_Int32 nRow )
704 throw( SQLException,
705 RuntimeException )
707 impl_EnsureNotDisposed();
708 //-------------------------------------------------------------------------
710 @returns
711 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
712 the result set.
715 ReacquireableGuard aGuard( m_aMutex );
716 OSL_ENSURE( nRow >= 0, "only positive values supported" );
717 if( !m_xResultSetOrigin.is() )
719 OSL_FAIL( "broadcaster was disposed already" );
720 return sal_False;
722 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
724 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
725 sal_Bool bAfterLastApplied = m_bAfterLastApplied;
726 sal_Bool bAfterLast = m_bAfterLast;
727 sal_Int32 nForwardOnly = m_nForwardOnly;
729 aGuard.clear();
731 if( bAfterLastApplied || nLastAppliedPos != nRow )
733 if( nForwardOnly == 1 )
735 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
736 throw SQLException();
738 sal_Int32 nN = nRow - nLastAppliedPos;
739 sal_Int32 nM;
740 for( nM = 0; nN--; nM++ )
742 if( !m_xResultSetOrigin->next() )
743 break;
746 aGuard.reacquire();
747 m_nLastAppliedPos += nM;
748 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
749 return nRow == m_nLastAppliedPos;
752 if( !nRow ) //absolute( 0 ) will throw exception
754 m_xResultSetOrigin->beforeFirst();
756 aGuard.reacquire();
757 m_nLastAppliedPos = 0;
758 m_bAfterLastApplied = sal_False;
759 return sal_False;
763 //move absolute, if !nLastAppliedPos
764 //because move relative would throw exception
765 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
767 sal_Bool bValid = m_xResultSetOrigin->absolute( nRow );
769 aGuard.reacquire();
770 m_nLastAppliedPos = nRow;
771 m_bAfterLastApplied = !bValid;
772 return bValid;
774 else
776 sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
778 aGuard.reacquire();
779 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
780 m_bAfterLastApplied = !bValid;
781 return bValid;
784 catch (const SQLException&)
786 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
788 sal_Int32 nN = nRow - nLastAppliedPos;
789 sal_Int32 nM;
790 for( nM = 0; nN--; nM++ )
792 if( !m_xResultSetOrigin->next() )
793 break;
796 aGuard.reacquire();
797 m_nLastAppliedPos += nM;
798 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
800 else
801 throw;
804 return nRow == m_nLastAppliedPos;
806 return sal_True;
809 //--------------------------------------------------------------------------
810 //--------------------------------------------------------------------------
811 //define for fetching data
812 //--------------------------------------------------------------------------
813 //--------------------------------------------------------------------------
815 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
816 sal_Bool bDirection = !!( \
817 nFetchDirection != FetchDirection::REVERSE ); \
818 FetchResult aResult = \
819 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
820 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
821 aCache.loadData( aResult ); \
822 sal_Int32 nMax = aCache.getMaxRow(); \
823 sal_Int32 nCurCount = m_nKnownCount; \
824 sal_Bool bIsFinalCount = aCache.hasKnownLast(); \
825 sal_Bool bCurIsFinalCount = m_bFinalCount; \
826 aGuard2.clear(); \
827 if( nMax > nCurCount ) \
828 impl_changeRowCount( nCurCount, nMax ); \
829 if( bIsFinalCount && !bCurIsFinalCount ) \
830 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
832 void SAL_CALL CachedContentResultSet
833 ::impl_fetchData( sal_Int32 nRow
834 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
835 throw( com::sun::star::uno::RuntimeException )
837 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
840 void SAL_CALL CachedContentResultSet
841 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
843 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
844 if( nNew <= nOld )
845 return;
847 //create PropertyChangeEvent and set value
848 PropertyChangeEvent aEvt;
850 osl::Guard< osl::Mutex > aGuard( m_aMutex );
851 aEvt.Source = static_cast< XPropertySet * >( this );
852 aEvt.Further = sal_False;
853 aEvt.OldValue <<= nOld;
854 aEvt.NewValue <<= nNew;
856 m_nKnownCount = nNew;
859 //send PropertyChangeEvent to listeners
860 impl_notifyPropertyChangeListeners( aEvt );
863 void SAL_CALL CachedContentResultSet
864 ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew )
866 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
867 if( ! (!bOld && bNew ) )
868 return;
870 //create PropertyChangeEvent and set value
871 PropertyChangeEvent aEvt;
873 osl::Guard< osl::Mutex > aGuard( m_aMutex );
874 aEvt.Source = static_cast< XPropertySet * >( this );
875 aEvt.Further = sal_False;
876 aEvt.OldValue <<= bOld;
877 aEvt.NewValue <<= bNew;
879 m_bFinalCount = bNew;
882 //send PropertyChangeEvent to listeners
883 impl_notifyPropertyChangeListeners( aEvt );
886 sal_Bool SAL_CALL CachedContentResultSet
887 ::impl_isKnownValidPosition( sal_Int32 nRow )
889 return m_nKnownCount && nRow
890 && nRow <= m_nKnownCount;
893 sal_Bool SAL_CALL CachedContentResultSet
894 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
896 if( !nRow )
897 return sal_True;
898 if( !m_bFinalCount )
899 return sal_False;
900 return nRow > m_nKnownCount;
904 //virtual
905 void SAL_CALL CachedContentResultSet
906 ::impl_initPropertySetInfo()
908 ContentResultSetWrapper::impl_initPropertySetInfo();
910 osl::Guard< osl::Mutex > aGuard( m_aMutex );
911 if( m_pMyPropSetInfo )
912 return;
913 m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
914 m_xMyPropertySetInfo = m_pMyPropSetInfo;
915 m_xPropertySetInfo = m_xMyPropertySetInfo;
918 //--------------------------------------------------------------------------
919 // XInterface methods. ( inherited )
920 //--------------------------------------------------------------------------
921 XINTERFACE_COMMON_IMPL( CachedContentResultSet )
923 Any SAL_CALL CachedContentResultSet
924 ::queryInterface( const Type& rType )
925 throw ( RuntimeException )
927 //list all interfaces inclusive baseclasses of interfaces
929 Any aRet = ContentResultSetWrapper::queryInterface( rType );
930 if( aRet.hasValue() )
931 return aRet;
933 aRet = cppu::queryInterface( rType,
934 static_cast< XTypeProvider* >( this ),
935 static_cast< XServiceInfo* >( this ) );
937 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
940 //--------------------------------------------------------------------------
941 // XTypeProvider methods.
942 //--------------------------------------------------------------------------
943 //list all interfaces exclusive baseclasses
944 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
945 , XTypeProvider
946 , XServiceInfo
947 , XComponent
948 , XCloseable
949 , XResultSetMetaDataSupplier
950 , XPropertySet
952 , XPropertyChangeListener
953 , XVetoableChangeListener
955 , XContentAccess
957 , XResultSet
958 , XRow );
960 //--------------------------------------------------------------------------
961 // XServiceInfo methods.
962 //--------------------------------------------------------------------------
964 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
965 OUString(
966 "com.sun.star.comp.ucb.CachedContentResultSet" ),
967 OUString(
968 CACHED_CONTENT_RESULTSET_SERVICE_NAME ) );
970 //--------------------------------------------------------------------------
971 // XPropertySet methods. ( inherited )
972 //--------------------------------------------------------------------------
974 // virtual
975 void SAL_CALL CachedContentResultSet
976 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
977 throw( UnknownPropertyException,
978 PropertyVetoException,
979 IllegalArgumentException,
980 WrappedTargetException,
981 RuntimeException )
983 impl_EnsureNotDisposed();
985 if( !getPropertySetInfo().is() )
987 OSL_FAIL( "broadcaster was disposed already" );
988 throw UnknownPropertyException();
991 Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
992 //throws UnknownPropertyException, if so
994 if( aProp.Attributes & PropertyAttribute::READONLY )
996 //It is assumed, that the properties
997 //'RowCount' and 'IsRowCountFinal' are readonly!
998 throw IllegalArgumentException();
1000 if( aProp.Name == CCRS_PropertySetInfo
1001 ::m_aPropertyNameForFetchDirection )
1003 //check value
1004 sal_Int32 nNew;
1005 if( !( aValue >>= nNew ) )
1007 throw IllegalArgumentException();
1010 if( nNew == FetchDirection::UNKNOWN )
1012 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1014 else if( !( nNew == FetchDirection::FORWARD
1015 || nNew == FetchDirection::REVERSE ) )
1017 throw IllegalArgumentException();
1020 //create PropertyChangeEvent and set value
1021 PropertyChangeEvent aEvt;
1023 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1024 aEvt.Source = static_cast< XPropertySet * >( this );
1025 aEvt.PropertyName = aPropertyName;
1026 aEvt.Further = sal_False;
1027 aEvt.PropertyHandle = m_pMyPropSetInfo->
1028 m_nFetchDirectionPropertyHandle;
1029 aEvt.OldValue <<= m_nFetchDirection;
1030 aEvt.NewValue <<= nNew;
1032 m_nFetchDirection = nNew;
1035 //send PropertyChangeEvent to listeners
1036 impl_notifyPropertyChangeListeners( aEvt );
1038 else if( aProp.Name == CCRS_PropertySetInfo
1039 ::m_aPropertyNameForFetchSize )
1041 //check value
1042 sal_Int32 nNew;
1043 if( !( aValue >>= nNew ) )
1045 throw IllegalArgumentException();
1048 if( nNew < 0 )
1050 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1053 //create PropertyChangeEvent and set value
1054 PropertyChangeEvent aEvt;
1056 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1057 aEvt.Source = static_cast< XPropertySet * >( this );
1058 aEvt.PropertyName = aPropertyName;
1059 aEvt.Further = sal_False;
1060 aEvt.PropertyHandle = m_pMyPropSetInfo->
1061 m_nFetchSizePropertyHandle;
1062 aEvt.OldValue <<= m_nFetchSize;
1063 aEvt.NewValue <<= nNew;
1065 m_nFetchSize = nNew;
1068 //send PropertyChangeEvent to listeners
1069 impl_notifyPropertyChangeListeners( aEvt );
1071 else
1073 impl_init_xPropertySetOrigin();
1075 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1076 if( !m_xPropertySetOrigin.is() )
1078 OSL_FAIL( "broadcaster was disposed already" );
1079 return;
1082 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1086 //--------------------------------------------------------------------------
1087 // virtual
1088 Any SAL_CALL CachedContentResultSet
1089 ::getPropertyValue( const OUString& rPropertyName )
1090 throw( UnknownPropertyException,
1091 WrappedTargetException,
1092 RuntimeException )
1094 impl_EnsureNotDisposed();
1096 if( !getPropertySetInfo().is() )
1098 OSL_FAIL( "broadcaster was disposed already" );
1099 throw UnknownPropertyException();
1102 Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1103 //throws UnknownPropertyException, if so
1105 Any aValue;
1106 if( rPropertyName == CCRS_PropertySetInfo
1107 ::m_aPropertyNameForCount )
1109 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1110 aValue <<= m_nKnownCount;
1112 else if( rPropertyName == CCRS_PropertySetInfo
1113 ::m_aPropertyNameForFinalCount )
1115 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1116 aValue <<= m_bFinalCount;
1118 else if( rPropertyName == CCRS_PropertySetInfo
1119 ::m_aPropertyNameForFetchSize )
1121 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1122 aValue <<= m_nFetchSize;
1124 else if( rPropertyName == CCRS_PropertySetInfo
1125 ::m_aPropertyNameForFetchDirection )
1127 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1128 aValue <<= m_nFetchDirection;
1130 else
1132 impl_init_xPropertySetOrigin();
1134 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1135 if( !m_xPropertySetOrigin.is() )
1137 OSL_FAIL( "broadcaster was disposed already" );
1138 throw UnknownPropertyException();
1141 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1143 return aValue;
1146 //--------------------------------------------------------------------------
1147 // own methods. ( inherited )
1148 //--------------------------------------------------------------------------
1150 //virtual
1151 void SAL_CALL CachedContentResultSet
1152 ::impl_disposing( const EventObject& rEventObject )
1153 throw( RuntimeException )
1156 impl_EnsureNotDisposed();
1157 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1158 //release all references to the broadcaster:
1159 m_xFetchProvider.clear();
1160 m_xFetchProviderForContentAccess.clear();
1162 ContentResultSetWrapper::impl_disposing( rEventObject );
1165 //virtual
1166 void SAL_CALL CachedContentResultSet
1167 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1168 throw( RuntimeException )
1170 impl_EnsureNotDisposed();
1172 PropertyChangeEvent aEvt( rEvt );
1173 aEvt.Source = static_cast< XPropertySet * >( this );
1174 aEvt.Further = sal_False;
1175 //---------
1177 if( CCRS_PropertySetInfo
1178 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1180 //don't notify foreign events on fetchsize and fetchdirection
1181 if( aEvt.PropertyName == CCRS_PropertySetInfo
1182 ::m_aPropertyNameForFetchSize
1183 || aEvt.PropertyName == CCRS_PropertySetInfo
1184 ::m_aPropertyNameForFetchDirection )
1185 return;
1187 //adjust my props 'RowCount' and 'IsRowCountFinal'
1188 if( aEvt.PropertyName == CCRS_PropertySetInfo
1189 ::m_aPropertyNameForCount )
1190 {//RowCount changed
1192 //check value
1193 sal_Int32 nNew = 0;
1194 if( !( aEvt.NewValue >>= nNew ) )
1196 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1197 return;
1200 impl_changeRowCount( m_nKnownCount, nNew );
1202 else if( aEvt.PropertyName == CCRS_PropertySetInfo
1203 ::m_aPropertyNameForFinalCount )
1204 {//IsRowCountFinal changed
1206 //check value
1207 sal_Bool bNew = sal_False;
1208 if( !( aEvt.NewValue >>= bNew ) )
1210 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1211 return;
1213 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1215 return;
1218 //-----------
1219 impl_notifyPropertyChangeListeners( aEvt );
1223 //virtual
1224 void SAL_CALL CachedContentResultSet
1225 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1226 throw( PropertyVetoException,
1227 RuntimeException )
1229 impl_EnsureNotDisposed();
1231 //don't notify events on my properties, cause they are not vetoable
1232 if( CCRS_PropertySetInfo
1233 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1235 return;
1239 PropertyChangeEvent aEvt( rEvt );
1240 aEvt.Source = static_cast< XPropertySet * >( this );
1241 aEvt.Further = sal_False;
1243 impl_notifyVetoableChangeListeners( aEvt );
1246 //--------------------------------------------------------------------------
1247 // XContentAccess methods. ( inherited ) ( -- position dependent )
1248 //--------------------------------------------------------------------------
1250 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1251 impl_EnsureNotDisposed(); \
1252 ReacquireableGuard aGuard( m_aMutex ); \
1253 sal_Int32 nRow = m_nRow; \
1254 sal_Int32 nFetchSize = m_nFetchSize; \
1255 sal_Int32 nFetchDirection = m_nFetchDirection; \
1256 if( !m_aCache##XXX.hasRow( nRow ) ) \
1258 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1260 if( !m_xFetchProviderForContentAccess.is() ) \
1262 OSL_FAIL( "broadcaster was disposed already" );\
1263 throw RuntimeException(); \
1265 aGuard.clear(); \
1266 if( impl_isForwardOnly() ) \
1267 applyPositionToOrigin( nRow ); \
1269 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1271 aGuard.reacquire(); \
1272 if( !m_aCache##XXX.hasRow( nRow ) ) \
1274 aGuard.clear(); \
1275 applyPositionToOrigin( nRow ); \
1276 TYPE aRet = ContentResultSetWrapper::queryXXX(); \
1277 if( m_xContentIdentifierMapping.is() ) \
1278 return m_xContentIdentifierMapping->map##XXX( aRet );\
1279 return aRet; \
1282 return m_aCache##XXX.get##XXX( nRow );
1284 //--------------------------------------------------------------------------
1285 // virtual
1286 OUString SAL_CALL CachedContentResultSet
1287 ::queryContentIdentifierString()
1288 throw( RuntimeException )
1290 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1293 //--------------------------------------------------------------------------
1294 // virtual
1295 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1296 ::queryContentIdentifier()
1297 throw( RuntimeException )
1299 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1302 //--------------------------------------------------------------------------
1303 // virtual
1304 Reference< XContent > SAL_CALL CachedContentResultSet
1305 ::queryContent()
1306 throw( RuntimeException )
1308 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1311 //-----------------------------------------------------------------
1312 // XResultSet methods. ( inherited )
1313 //-----------------------------------------------------------------
1314 //virtual
1316 sal_Bool SAL_CALL CachedContentResultSet
1317 ::next()
1318 throw( SQLException,
1319 RuntimeException )
1321 impl_EnsureNotDisposed();
1323 ReacquireableGuard aGuard( m_aMutex );
1324 //after last
1325 if( m_bAfterLast )
1326 return sal_False;
1327 //last
1328 aGuard.clear();
1329 if( isLast() )
1331 aGuard.reacquire();
1332 m_nRow++;
1333 m_bAfterLast = sal_True;
1334 return sal_False;
1336 aGuard.reacquire();
1337 //known valid position
1338 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1340 m_nRow++;
1341 return sal_True;
1344 //unknown position
1345 sal_Int32 nRow = m_nRow;
1346 aGuard.clear();
1348 sal_Bool bValid = applyPositionToOrigin( nRow + 1 );
1350 aGuard.reacquire();
1351 m_nRow = nRow + 1;
1352 m_bAfterLast = !bValid;
1353 return bValid;
1356 //virtual
1357 sal_Bool SAL_CALL CachedContentResultSet
1358 ::previous()
1359 throw( SQLException,
1360 RuntimeException )
1362 impl_EnsureNotDisposed();
1364 if( impl_isForwardOnly() )
1365 throw SQLException();
1367 ReacquireableGuard aGuard( m_aMutex );
1368 //before first ?:
1369 if( !m_bAfterLast && !m_nRow )
1370 return sal_False;
1371 //first ?:
1372 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1374 m_nRow--;
1375 m_bAfterLast = sal_False;
1376 return sal_False;
1378 //known valid position ?:
1379 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1381 m_nRow--;
1382 m_bAfterLast = sal_False;
1383 return sal_True;
1385 //unknown position:
1386 sal_Int32 nRow = m_nRow;
1387 aGuard.clear();
1389 sal_Bool bValid = applyPositionToOrigin( nRow - 1 );
1391 aGuard.reacquire();
1392 m_nRow = nRow - 1;
1393 m_bAfterLast = sal_False;
1394 return bValid;
1397 //virtual
1398 sal_Bool SAL_CALL CachedContentResultSet
1399 ::absolute( sal_Int32 row )
1400 throw( SQLException,
1401 RuntimeException )
1403 impl_EnsureNotDisposed();
1405 if( !row )
1406 throw SQLException();
1408 if( impl_isForwardOnly() )
1409 throw SQLException();
1411 ReacquireableGuard aGuard( m_aMutex );
1413 if( !m_xResultSetOrigin.is() )
1415 OSL_FAIL( "broadcaster was disposed already" );
1416 return sal_False;
1418 if( row < 0 )
1420 if( m_bFinalCount )
1422 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1423 sal_Bool bValid = sal_True;
1424 if( nNewRow <= 0 )
1426 nNewRow = 0;
1427 bValid = sal_False;
1429 m_nRow = nNewRow;
1430 m_bAfterLast = sal_False;
1431 return bValid;
1433 //unknown final count:
1434 aGuard.clear();
1436 // Solaris has problems catching or propagating derived exceptions
1437 // when only the base class is known, so make ResultSetException
1438 // (derived from SQLException) known here:
1439 sal_Bool bValid;
1442 bValid = m_xResultSetOrigin->absolute( row );
1444 catch (const ResultSetException&)
1446 throw;
1449 aGuard.reacquire();
1450 if( m_bFinalCount )
1452 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1453 if( nNewRow < 0 )
1454 nNewRow = 0;
1455 m_nLastAppliedPos = nNewRow;
1456 m_nRow = nNewRow;
1457 m_bAfterLastApplied = m_bAfterLast = sal_False;
1458 return bValid;
1460 aGuard.clear();
1462 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1464 aGuard.reacquire();
1465 m_nLastAppliedPos = nCurRow;
1466 m_nRow = nCurRow;
1467 m_bAfterLast = sal_False;
1468 return nCurRow != 0;
1470 //row > 0:
1471 if( m_bFinalCount )
1473 if( row > m_nKnownCount )
1475 m_nRow = m_nKnownCount + 1;
1476 m_bAfterLast = sal_True;
1477 return sal_False;
1479 m_nRow = row;
1480 m_bAfterLast = sal_False;
1481 return sal_True;
1483 //unknown new position:
1484 aGuard.clear();
1486 sal_Bool bValid = m_xResultSetOrigin->absolute( row );
1488 aGuard.reacquire();
1489 if( m_bFinalCount )
1491 sal_Int32 nNewRow = row;
1492 if( nNewRow > m_nKnownCount )
1494 nNewRow = m_nKnownCount + 1;
1495 m_bAfterLastApplied = m_bAfterLast = sal_True;
1497 else
1498 m_bAfterLastApplied = m_bAfterLast = sal_False;
1500 m_nLastAppliedPos = nNewRow;
1501 m_nRow = nNewRow;
1502 return bValid;
1504 aGuard.clear();
1506 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1507 sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1509 aGuard.reacquire();
1510 m_nLastAppliedPos = nCurRow;
1511 m_nRow = nCurRow;
1512 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1513 return nCurRow && !bIsAfterLast;
1516 //virtual
1517 sal_Bool SAL_CALL CachedContentResultSet
1518 ::relative( sal_Int32 rows )
1519 throw( SQLException,
1520 RuntimeException )
1522 impl_EnsureNotDisposed();
1524 if( impl_isForwardOnly() )
1525 throw SQLException();
1527 ReacquireableGuard aGuard( m_aMutex );
1528 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1529 throw SQLException();
1531 if( !rows )
1532 return sal_True;
1534 sal_Int32 nNewRow = m_nRow + rows;
1535 if( nNewRow < 0 )
1536 nNewRow = 0;
1538 if( impl_isKnownValidPosition( nNewRow ) )
1540 m_nRow = nNewRow;
1541 m_bAfterLast = sal_False;
1542 return sal_True;
1544 else
1546 //known invalid new position:
1547 if( nNewRow == 0 )
1549 m_bAfterLast = sal_False;
1550 m_nRow = 0;
1551 return sal_False;
1553 if( m_bFinalCount && nNewRow > m_nKnownCount )
1555 m_bAfterLast = sal_True;
1556 m_nRow = m_nKnownCount + 1;
1557 return sal_False;
1559 //unknown new position:
1560 aGuard.clear();
1561 sal_Bool bValid = applyPositionToOrigin( nNewRow );
1563 aGuard.reacquire();
1564 m_nRow = nNewRow;
1565 m_bAfterLast = !bValid && nNewRow > 0;
1566 return bValid;
1571 //virtual
1572 sal_Bool SAL_CALL CachedContentResultSet
1573 ::first()
1574 throw( SQLException,
1575 RuntimeException )
1577 impl_EnsureNotDisposed();
1579 if( impl_isForwardOnly() )
1580 throw SQLException();
1582 ReacquireableGuard aGuard( m_aMutex );
1583 if( impl_isKnownValidPosition( 1 ) )
1585 m_nRow = 1;
1586 m_bAfterLast = sal_False;
1587 return sal_True;
1589 if( impl_isKnownInvalidPosition( 1 ) )
1591 m_nRow = 1;
1592 m_bAfterLast = sal_False;
1593 return sal_False;
1595 //unknown position
1596 aGuard.clear();
1598 sal_Bool bValid = applyPositionToOrigin( 1 );
1600 aGuard.reacquire();
1601 m_nRow = 1;
1602 m_bAfterLast = sal_False;
1603 return bValid;
1606 //virtual
1607 sal_Bool SAL_CALL CachedContentResultSet
1608 ::last()
1609 throw( SQLException,
1610 RuntimeException )
1612 impl_EnsureNotDisposed();
1614 if( impl_isForwardOnly() )
1615 throw SQLException();
1617 ReacquireableGuard aGuard( m_aMutex );
1618 if( m_bFinalCount )
1620 m_nRow = m_nKnownCount;
1621 m_bAfterLast = sal_False;
1622 return m_nKnownCount != 0;
1624 //unknown position
1625 if( !m_xResultSetOrigin.is() )
1627 OSL_FAIL( "broadcaster was disposed already" );
1628 return sal_False;
1630 aGuard.clear();
1632 sal_Bool bValid = m_xResultSetOrigin->last();
1634 aGuard.reacquire();
1635 m_bAfterLastApplied = m_bAfterLast = sal_False;
1636 if( m_bFinalCount )
1638 m_nLastAppliedPos = m_nKnownCount;
1639 m_nRow = m_nKnownCount;
1640 return bValid;
1642 aGuard.clear();
1644 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1646 aGuard.reacquire();
1647 m_nLastAppliedPos = nCurRow;
1648 m_nRow = nCurRow;
1649 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1650 m_nKnownCount = nCurRow;
1651 m_bFinalCount = sal_True;
1652 return nCurRow != 0;
1655 //virtual
1656 void SAL_CALL CachedContentResultSet
1657 ::beforeFirst()
1658 throw( SQLException,
1659 RuntimeException )
1661 impl_EnsureNotDisposed();
1663 if( impl_isForwardOnly() )
1664 throw SQLException();
1666 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1667 m_nRow = 0;
1668 m_bAfterLast = sal_False;
1671 //virtual
1672 void SAL_CALL CachedContentResultSet
1673 ::afterLast()
1674 throw( SQLException,
1675 RuntimeException )
1677 impl_EnsureNotDisposed();
1679 if( impl_isForwardOnly() )
1680 throw SQLException();
1682 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1683 m_nRow = 1;
1684 m_bAfterLast = sal_True;
1687 //virtual
1688 sal_Bool SAL_CALL CachedContentResultSet
1689 ::isAfterLast()
1690 throw( SQLException,
1691 RuntimeException )
1693 impl_EnsureNotDisposed();
1695 ReacquireableGuard aGuard( m_aMutex );
1696 if( !m_bAfterLast )
1697 return sal_False;
1698 if( m_nKnownCount )
1699 return m_bAfterLast;
1700 if( m_bFinalCount )
1701 return sal_False;
1703 if( !m_xResultSetOrigin.is() )
1705 OSL_FAIL( "broadcaster was disposed already" );
1706 return sal_False;
1708 aGuard.clear();
1710 //find out whethter the original resultset contains rows or not
1711 m_xResultSetOrigin->afterLast();
1713 aGuard.reacquire();
1714 m_bAfterLastApplied = sal_True;
1715 aGuard.clear();
1717 return m_xResultSetOrigin->isAfterLast();
1720 //virtual
1721 sal_Bool SAL_CALL CachedContentResultSet
1722 ::isBeforeFirst()
1723 throw( SQLException,
1724 RuntimeException )
1726 impl_EnsureNotDisposed();
1728 ReacquireableGuard aGuard( m_aMutex );
1729 if( m_bAfterLast )
1730 return sal_False;
1731 if( m_nRow )
1732 return sal_False;
1733 if( m_nKnownCount )
1734 return !m_nRow;
1735 if( m_bFinalCount )
1736 return sal_False;
1738 if( !m_xResultSetOrigin.is() )
1740 OSL_FAIL( "broadcaster was disposed already" );
1741 return sal_False;
1743 aGuard.clear();
1745 //find out whethter the original resultset contains rows or not
1746 m_xResultSetOrigin->beforeFirst();
1748 aGuard.reacquire();
1749 m_bAfterLastApplied = sal_False;
1750 m_nLastAppliedPos = 0;
1751 aGuard.clear();
1753 return m_xResultSetOrigin->isBeforeFirst();
1756 //virtual
1757 sal_Bool SAL_CALL CachedContentResultSet
1758 ::isFirst()
1759 throw( SQLException,
1760 RuntimeException )
1762 impl_EnsureNotDisposed();
1764 sal_Int32 nRow = 0;
1765 Reference< XResultSet > xResultSetOrigin;
1768 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1769 if( m_bAfterLast )
1770 return sal_False;
1771 if( m_nRow != 1 )
1772 return sal_False;
1773 if( m_nKnownCount )
1774 return m_nRow == 1;
1775 if( m_bFinalCount )
1776 return sal_False;
1778 nRow = m_nRow;
1779 xResultSetOrigin = m_xResultSetOrigin;
1782 //need to ask origin
1784 if( applyPositionToOrigin( nRow ) )
1785 return xResultSetOrigin->isFirst();
1786 else
1787 return sal_False;
1791 //virtual
1792 sal_Bool SAL_CALL CachedContentResultSet
1793 ::isLast()
1794 throw( SQLException,
1795 RuntimeException )
1797 impl_EnsureNotDisposed();
1799 sal_Int32 nRow = 0;
1800 Reference< XResultSet > xResultSetOrigin;
1802 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1803 if( m_bAfterLast )
1804 return sal_False;
1805 if( m_nRow < m_nKnownCount )
1806 return sal_False;
1807 if( m_bFinalCount )
1808 return m_nKnownCount && m_nRow == m_nKnownCount;
1810 nRow = m_nRow;
1811 xResultSetOrigin = m_xResultSetOrigin;
1814 //need to ask origin
1816 if( applyPositionToOrigin( nRow ) )
1817 return xResultSetOrigin->isLast();
1818 else
1819 return sal_False;
1824 //virtual
1825 sal_Int32 SAL_CALL CachedContentResultSet
1826 ::getRow()
1827 throw( SQLException,
1828 RuntimeException )
1830 impl_EnsureNotDisposed();
1832 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1833 if( m_bAfterLast )
1834 return 0;
1835 return m_nRow;
1838 //virtual
1839 void SAL_CALL CachedContentResultSet
1840 ::refreshRow()
1841 throw( SQLException,
1842 RuntimeException )
1844 impl_EnsureNotDisposed();
1846 //the ContentResultSet is static and will not change
1847 //therefore we don't need to reload anything
1850 //virtual
1851 sal_Bool SAL_CALL CachedContentResultSet
1852 ::rowUpdated()
1853 throw( SQLException,
1854 RuntimeException )
1856 impl_EnsureNotDisposed();
1858 //the ContentResultSet is static and will not change
1859 return sal_False;
1861 //virtual
1862 sal_Bool SAL_CALL CachedContentResultSet
1863 ::rowInserted()
1864 throw( SQLException,
1865 RuntimeException )
1867 impl_EnsureNotDisposed();
1869 //the ContentResultSet is static and will not change
1870 return sal_False;
1873 //virtual
1874 sal_Bool SAL_CALL CachedContentResultSet
1875 ::rowDeleted()
1876 throw( SQLException,
1877 RuntimeException )
1879 impl_EnsureNotDisposed();
1881 //the ContentResultSet is static and will not change
1882 return sal_False;
1885 //virtual
1886 Reference< XInterface > SAL_CALL CachedContentResultSet
1887 ::getStatement()
1888 throw( SQLException,
1889 RuntimeException )
1891 impl_EnsureNotDisposed();
1892 //@todo ?return anything
1893 return Reference< XInterface >();
1896 //-----------------------------------------------------------------
1897 // XRow methods. ( inherited )
1898 //-----------------------------------------------------------------
1900 //virtual
1901 sal_Bool SAL_CALL CachedContentResultSet
1902 ::wasNull()
1903 throw( SQLException,
1904 RuntimeException )
1906 impl_EnsureNotDisposed();
1907 impl_init_xRowOrigin();
1909 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1910 if( m_bLastReadWasFromCache )
1911 return m_bLastCachedReadWasNull;
1912 if( !m_xRowOrigin.is() )
1914 OSL_FAIL( "broadcaster was disposed already" );
1915 return sal_False;
1918 return m_xRowOrigin->wasNull();
1921 //virtual
1922 OUString SAL_CALL CachedContentResultSet
1923 ::getString( sal_Int32 columnIndex )
1924 throw( SQLException,
1925 RuntimeException )
1927 XROW_GETXXX( getString, OUString );
1930 //virtual
1931 sal_Bool SAL_CALL CachedContentResultSet
1932 ::getBoolean( sal_Int32 columnIndex )
1933 throw( SQLException,
1934 RuntimeException )
1936 XROW_GETXXX( getBoolean, sal_Bool );
1939 //virtual
1940 sal_Int8 SAL_CALL CachedContentResultSet
1941 ::getByte( sal_Int32 columnIndex )
1942 throw( SQLException,
1943 RuntimeException )
1945 XROW_GETXXX( getByte, sal_Int8 );
1948 //virtual
1949 sal_Int16 SAL_CALL CachedContentResultSet
1950 ::getShort( sal_Int32 columnIndex )
1951 throw( SQLException,
1952 RuntimeException )
1954 XROW_GETXXX( getShort, sal_Int16 );
1957 //virtual
1958 sal_Int32 SAL_CALL CachedContentResultSet
1959 ::getInt( sal_Int32 columnIndex )
1960 throw( SQLException,
1961 RuntimeException )
1963 XROW_GETXXX( getInt, sal_Int32 );
1966 //virtual
1967 sal_Int64 SAL_CALL CachedContentResultSet
1968 ::getLong( sal_Int32 columnIndex )
1969 throw( SQLException,
1970 RuntimeException )
1972 XROW_GETXXX( getLong, sal_Int64 );
1975 //virtual
1976 float SAL_CALL CachedContentResultSet
1977 ::getFloat( sal_Int32 columnIndex )
1978 throw( SQLException,
1979 RuntimeException )
1981 XROW_GETXXX( getFloat, float );
1984 //virtual
1985 double SAL_CALL CachedContentResultSet
1986 ::getDouble( sal_Int32 columnIndex )
1987 throw( SQLException,
1988 RuntimeException )
1990 XROW_GETXXX( getDouble, double );
1993 //virtual
1994 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
1995 ::getBytes( sal_Int32 columnIndex )
1996 throw( SQLException,
1997 RuntimeException )
1999 XROW_GETXXX( getBytes, Sequence< sal_Int8 > );
2002 //virtual
2003 Date SAL_CALL CachedContentResultSet
2004 ::getDate( sal_Int32 columnIndex )
2005 throw( SQLException,
2006 RuntimeException )
2008 XROW_GETXXX( getDate, Date );
2011 //virtual
2012 Time SAL_CALL CachedContentResultSet
2013 ::getTime( sal_Int32 columnIndex )
2014 throw( SQLException,
2015 RuntimeException )
2017 XROW_GETXXX( getTime, Time );
2020 //virtual
2021 DateTime SAL_CALL CachedContentResultSet
2022 ::getTimestamp( sal_Int32 columnIndex )
2023 throw( SQLException,
2024 RuntimeException )
2026 XROW_GETXXX( getTimestamp, DateTime );
2029 //virtual
2030 Reference< com::sun::star::io::XInputStream >
2031 SAL_CALL CachedContentResultSet
2032 ::getBinaryStream( sal_Int32 columnIndex )
2033 throw( SQLException,
2034 RuntimeException )
2036 XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > );
2039 //virtual
2040 Reference< com::sun::star::io::XInputStream >
2041 SAL_CALL CachedContentResultSet
2042 ::getCharacterStream( sal_Int32 columnIndex )
2043 throw( SQLException,
2044 RuntimeException )
2046 XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > );
2049 //virtual
2050 Any SAL_CALL CachedContentResultSet
2051 ::getObject( sal_Int32 columnIndex,
2052 const Reference<
2053 com::sun::star::container::XNameAccess >& typeMap )
2054 throw( SQLException,
2055 RuntimeException )
2057 //if you change this macro please pay attention to
2058 //define XROW_GETXXX, where this is similar implemented
2060 ReacquireableGuard aGuard( m_aMutex );
2061 sal_Int32 nRow = m_nRow;
2062 sal_Int32 nFetchSize = m_nFetchSize;
2063 sal_Int32 nFetchDirection = m_nFetchDirection;
2064 if( !m_aCache.hasRow( nRow ) )
2066 if( !m_aCache.hasCausedException( nRow ) )
2068 if( !m_xFetchProvider.is() )
2070 OSL_FAIL( "broadcaster was disposed already" );
2071 return Any();
2073 aGuard.clear();
2075 impl_fetchData( nRow, nFetchSize, nFetchDirection );
2077 aGuard.reacquire();
2078 if( !m_aCache.hasRow( nRow ) )
2080 m_bLastReadWasFromCache = sal_False;
2081 aGuard.clear();
2082 applyPositionToOrigin( nRow );
2083 impl_init_xRowOrigin();
2084 return m_xRowOrigin->getObject( columnIndex, typeMap );
2087 //@todo: pay attention to typeMap
2088 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2089 Any aRet;
2090 m_bLastReadWasFromCache = sal_True;
2091 m_bLastCachedReadWasNull = !( rValue >>= aRet );
2092 return aRet;
2095 //virtual
2096 Reference< XRef > SAL_CALL CachedContentResultSet
2097 ::getRef( sal_Int32 columnIndex )
2098 throw( SQLException,
2099 RuntimeException )
2101 XROW_GETXXX( getRef, Reference< XRef > );
2104 //virtual
2105 Reference< XBlob > SAL_CALL CachedContentResultSet
2106 ::getBlob( sal_Int32 columnIndex )
2107 throw( SQLException,
2108 RuntimeException )
2110 XROW_GETXXX( getBlob, Reference< XBlob > );
2113 //virtual
2114 Reference< XClob > SAL_CALL CachedContentResultSet
2115 ::getClob( sal_Int32 columnIndex )
2116 throw( SQLException,
2117 RuntimeException )
2119 XROW_GETXXX( getClob, Reference< XClob > );
2122 //virtual
2123 Reference< XArray > SAL_CALL CachedContentResultSet
2124 ::getArray( sal_Int32 columnIndex )
2125 throw( SQLException,
2126 RuntimeException )
2128 XROW_GETXXX( getArray, Reference< XArray > );
2131 //-----------------------------------------------------------------
2132 // Type Converter Support
2133 //-----------------------------------------------------------------
2135 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2137 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2139 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2141 m_bTriedToGetTypeConverter = sal_True;
2142 m_xTypeConverter = Reference< XTypeConverter >( Converter::create(m_xContext) );
2144 OSL_ENSURE( m_xTypeConverter.is(),
2145 "PropertyValueSet::getTypeConverter() - "
2146 "Service 'com.sun.star.script.Converter' n/a!" );
2148 return m_xTypeConverter;
2151 //--------------------------------------------------------------------------
2152 //--------------------------------------------------------------------------
2153 // class CachedContentResultSetFactory
2154 //--------------------------------------------------------------------------
2155 //--------------------------------------------------------------------------
2157 CachedContentResultSetFactory::CachedContentResultSetFactory(
2158 const Reference< XComponentContext > & rxContext )
2160 m_xContext = rxContext;
2163 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2167 //--------------------------------------------------------------------------
2168 // CachedContentResultSetFactory XInterface methods.
2169 //--------------------------------------------------------------------------
2171 XINTERFACE_IMPL_3( CachedContentResultSetFactory,
2172 XTypeProvider,
2173 XServiceInfo,
2174 XCachedContentResultSetFactory );
2176 //--------------------------------------------------------------------------
2177 // CachedContentResultSetFactory XTypeProvider methods.
2178 //--------------------------------------------------------------------------
2180 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2181 XTypeProvider,
2182 XServiceInfo,
2183 XCachedContentResultSetFactory );
2185 //--------------------------------------------------------------------------
2186 // CachedContentResultSetFactory XServiceInfo methods.
2187 //--------------------------------------------------------------------------
2189 XSERVICEINFO_IMPL_1_CTX( CachedContentResultSetFactory,
2190 OUString( "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2191 OUString( CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2193 //--------------------------------------------------------------------------
2194 // Service factory implementation.
2195 //--------------------------------------------------------------------------
2197 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2199 //--------------------------------------------------------------------------
2200 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2201 //--------------------------------------------------------------------------
2203 //virtual
2204 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2205 ::createCachedContentResultSet(
2206 const Reference< XResultSet > & xSource,
2207 const Reference< XContentIdentifierMapping > & xMapping )
2208 throw( com::sun::star::uno::RuntimeException )
2210 Reference< XResultSet > xRet;
2211 xRet = new CachedContentResultSet( m_xContext, xSource, xMapping );
2212 return xRet;
2215 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */