Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blob20b35576975452eac7b75189dca516bce88328d1
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/sdbc/SQLException.hpp>
24 #include <com/sun/star/ucb/FetchError.hpp>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/script/CannotConvertException.hpp>
27 #include <com/sun/star/script/Converter.hpp>
28 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
29 #include <rtl/ustring.hxx>
30 #include <o3tl/any.hxx>
31 #include <osl/diagnose.h>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <cppuhelper/queryinterface.hxx>
34 #include <ucbhelper/getcomponentcontext.hxx>
35 #include <ucbhelper/macros.hxx>
36 #include <memory>
38 using namespace com::sun::star::beans;
39 using namespace com::sun::star::lang;
40 using namespace com::sun::star::script;
41 using namespace com::sun::star::sdbc;
42 using namespace com::sun::star::ucb;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::util;
45 using namespace cppu;
48 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
49 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
51 //if you change this function template please pay attention to
52 //function getObject, where this is similar implemented
54 template<typename T> T CachedContentResultSet::rowOriginGet(
55 T (SAL_CALL css::sdbc::XRow::* f)(sal_Int32), sal_Int32 columnIndex)
57 impl_EnsureNotDisposed();
58 osl::ResettableMutexGuard aGuard(m_aMutex);
59 sal_Int32 nRow = m_nRow;
60 sal_Int32 nFetchSize = m_nFetchSize;
61 sal_Int32 nFetchDirection = m_nFetchDirection;
62 if( !m_aCache.hasRow( nRow ) )
64 bool isCleared = false;
65 if( !m_aCache.hasCausedException( nRow ) )
67 if( !m_xFetchProvider.is() )
69 OSL_FAIL( "broadcaster was disposed already" );
70 throw SQLException();
72 aGuard.clear();
73 isCleared = true;
74 if( impl_isForwardOnly() )
75 applyPositionToOrigin( nRow );
77 impl_fetchData( nRow, nFetchSize, nFetchDirection );
79 if (isCleared)
81 aGuard.reset();
83 if( !m_aCache.hasRow( nRow ) )
85 m_bLastReadWasFromCache = false;
86 aGuard.clear();
87 applyPositionToOrigin( nRow );
88 impl_init_xRowOrigin();
89 return (m_xRowOrigin.get()->*f)( columnIndex );
92 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
93 T aRet = T();
94 m_bLastReadWasFromCache = true;
95 m_bLastCachedReadWasNull = !( rValue >>= aRet );
96 /* Last chance. Try type converter service... */
97 if ( m_bLastCachedReadWasNull && rValue.hasValue() )
99 Reference< XTypeConverter > xConverter = getTypeConverter();
100 if ( xConverter.is() )
104 Any aConvAny = xConverter->convertTo(
105 rValue,
106 cppu::UnoType<T>::get() );
107 m_bLastCachedReadWasNull = !( aConvAny >>= aRet );
109 catch (const IllegalArgumentException&)
112 catch (const CannotConvertException&)
117 return aRet;
121 // CCRS_Cache methods
124 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
125 const Reference< XContentIdentifierMapping > & xMapping )
126 : m_xContentIdentifierMapping( xMapping )
130 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
134 void CachedContentResultSet::CCRS_Cache
135 ::clear()
137 m_pResult.reset();
138 clearMappedReminder();
141 void CachedContentResultSet::CCRS_Cache
142 ::loadData( const FetchResult& rResult )
144 clear();
145 m_pResult.reset( new FetchResult( rResult ) );
148 bool CachedContentResultSet::CCRS_Cache
149 ::hasRow( sal_Int32 row )
151 if( !m_pResult )
152 return false;
153 sal_Int32 nStart = m_pResult->StartIndex;
154 sal_Int32 nEnd = nStart;
155 if( m_pResult->Orientation )
156 nEnd += m_pResult->Rows.getLength() - 1;
157 else
158 nStart -= m_pResult->Rows.getLength() + 1;
160 return nStart <= row && row <= nEnd;
163 sal_Int32 CachedContentResultSet::CCRS_Cache
164 ::getMaxRow() const
166 if( !m_pResult )
167 return 0;
168 sal_Int32 nEnd = m_pResult->StartIndex;
169 if( m_pResult->Orientation )
170 return nEnd += m_pResult->Rows.getLength() - 1;
171 else
172 return nEnd;
175 bool CachedContentResultSet::CCRS_Cache
176 ::hasKnownLast() const
178 if( !m_pResult )
179 return false;
181 return ( m_pResult->FetchError & FetchError::ENDOFDATA )
182 && m_pResult->Orientation
183 && m_pResult->Rows.hasElements();
186 bool CachedContentResultSet::CCRS_Cache
187 ::hasCausedException( sal_Int32 nRow )
189 if( !m_pResult )
190 return false;
191 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
192 return false;
194 sal_Int32 nEnd = m_pResult->StartIndex;
195 if( m_pResult->Orientation )
196 nEnd += m_pResult->Rows.getLength();
198 return nRow == nEnd+1;
201 Any& CachedContentResultSet::CCRS_Cache
202 ::getRowAny( sal_Int32 nRow )
204 if( !nRow )
205 throw SQLException();
206 if( !m_pResult )
207 throw SQLException();
208 if( !hasRow( nRow ) )
209 throw SQLException();
211 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
212 if( nDiff < 0 )
213 nDiff *= -1;
215 return (m_pResult->Rows)[nDiff];
218 void CachedContentResultSet::CCRS_Cache
219 ::remindMapped( sal_Int32 nRow )
221 //remind that this row was mapped
222 if( !m_pResult )
223 return;
224 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
225 if( nDiff < 0 )
226 nDiff *= -1;
227 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
228 if( nDiff < pMappedReminder->getLength() )
229 (*pMappedReminder)[nDiff] = true;
232 bool CachedContentResultSet::CCRS_Cache
233 ::isRowMapped( sal_Int32 nRow )
235 if( !m_pMappedReminder || !m_pResult )
236 return false;
237 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
238 if( nDiff < 0 )
239 nDiff *= -1;
240 if( nDiff < m_pMappedReminder->getLength() )
241 return (*m_pMappedReminder)[nDiff];
242 return false;
245 void CachedContentResultSet::CCRS_Cache
246 ::clearMappedReminder()
248 m_pMappedReminder.reset();
251 Sequence< sal_Bool >* CachedContentResultSet::CCRS_Cache
252 ::getMappedReminder()
254 if( !m_pMappedReminder )
256 sal_Int32 nCount = m_pResult->Rows.getLength();
257 m_pMappedReminder.reset(new Sequence< sal_Bool >( nCount ));
258 std::fill(m_pMappedReminder->begin(), m_pMappedReminder->end(), false);
260 return m_pMappedReminder.get();
263 const Any& CachedContentResultSet::CCRS_Cache
264 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
266 if( !nColumnIndex )
267 throw SQLException();
268 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
270 Any& rRow = getRowAny( nRow );
271 Sequence< Any > aValue;
272 rRow >>= aValue;
273 if( m_xContentIdentifierMapping->mapRow( aValue ) )
275 rRow <<= aValue;
276 remindMapped( nRow );
278 else
279 m_xContentIdentifierMapping.clear();
281 auto & rowAny = getRowAny(nRow);
282 auto rRow = o3tl::doAccess<Sequence<Any>>(rowAny);
284 if( nColumnIndex > rRow->getLength() )
285 throw SQLException();
286 return (*rRow)[nColumnIndex-1];
289 OUString const & CachedContentResultSet::CCRS_Cache
290 ::getContentIdentifierString( sal_Int32 nRow )
294 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
296 Any& rRow = getRowAny( nRow );
297 OUString aValue;
298 rRow >>= aValue;
299 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
300 remindMapped( nRow );
302 return *o3tl::doAccess<OUString>(getRowAny(nRow));
304 catch(const SQLException& ex)
306 css::uno::Any anyEx = cppu::getCaughtException();
307 throw css::lang::WrappedTargetRuntimeException( ex.Message,
308 css::uno::Reference< css::uno::XInterface >(),
309 anyEx );
313 Reference< XContentIdentifier > CachedContentResultSet::CCRS_Cache
314 ::getContentIdentifier( sal_Int32 nRow )
318 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
320 Any& rRow = getRowAny( nRow );
321 Reference< XContentIdentifier > aValue;
322 rRow >>= aValue;
323 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
324 remindMapped( nRow );
326 return *o3tl::doAccess<Reference<XContentIdentifier>>(getRowAny(nRow));
328 catch(const SQLException& ex)
330 css::uno::Any anyEx = cppu::getCaughtException();
331 throw css::lang::WrappedTargetRuntimeException( ex.Message,
332 css::uno::Reference< css::uno::XInterface >(),
333 anyEx );
337 Reference< XContent > CachedContentResultSet::CCRS_Cache
338 ::getContent( sal_Int32 nRow )
342 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
344 Any& rRow = getRowAny( nRow );
345 Reference< XContent > aValue;
346 rRow >>= aValue;
347 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
348 remindMapped( nRow );
350 return *o3tl::doAccess<Reference<XContent>>(getRowAny(nRow));
352 catch (const SQLException& ex)
354 css::uno::Any anyEx = cppu::getCaughtException();
355 throw css::lang::WrappedTargetRuntimeException( ex.Message,
356 css::uno::Reference< css::uno::XInterface >(),
357 anyEx );
362 // class CCRS_PropertySetInfo
365 class CCRS_PropertySetInfo :
366 public cppu::OWeakObject,
367 public css::lang::XTypeProvider,
368 public css::beans::XPropertySetInfo
370 friend class CachedContentResultSet;
372 //my Properties
373 std::unique_ptr<Sequence< css::beans::Property >>
374 m_pProperties;
376 long m_nFetchSizePropertyHandle;
377 long m_nFetchDirectionPropertyHandle;
379 private:
380 sal_Int32
381 impl_getRemainedHandle() const;
383 bool
384 impl_queryProperty(
385 const OUString& rName
386 , css::beans::Property& rProp ) const;
387 sal_Int32
388 impl_getPos( const OUString& rName ) const;
390 static bool
391 impl_isMyPropertyName( const OUString& rName );
393 public:
394 explicit CCRS_PropertySetInfo( Reference<
395 XPropertySetInfo > const & xPropertySetInfoOrigin );
397 // XInterface
398 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
399 virtual void SAL_CALL acquire()
400 throw() override;
401 virtual void SAL_CALL release()
402 throw() override;
404 // XTypeProvider
405 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
406 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
408 // XPropertySetInfo
409 virtual Sequence< css::beans::Property > SAL_CALL
410 getProperties() override;
412 virtual css::beans::Property SAL_CALL
413 getPropertyByName( const OUString& aName ) override;
415 virtual sal_Bool SAL_CALL
416 hasPropertyByName( const OUString& Name ) override;
419 //some helping variables ( names for my special properties )
420 static const char g_sPropertyNameForCount[] = "RowCount";
421 static const char g_sPropertyNameForFinalCount[] = "IsRowCountFinal";
422 static const char g_sPropertyNameForFetchSize[] = "FetchSize";
423 static const char g_sPropertyNameForFetchDirection[] = "FetchDirection";
425 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
426 Reference< XPropertySetInfo > const & xInfo )
427 : m_nFetchSizePropertyHandle( -1 )
428 , m_nFetchDirectionPropertyHandle( -1 )
430 //initialize list of properties:
432 // it is required, that the received xInfo contains the two
433 // properties with names 'g_sPropertyNameForCount' and
434 // 'g_sPropertyNameForFinalCount'
436 if( xInfo.is() )
438 Sequence<Property> aProps = xInfo->getProperties();
439 m_pProperties.reset( new Sequence<Property> ( aProps ) );
441 else
443 OSL_FAIL( "The received XPropertySetInfo doesn't contain required properties" );
444 m_pProperties.reset( new Sequence<Property> );
447 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
448 sal_Int32 nFetchSize = impl_getPos( g_sPropertyNameForFetchSize );
449 sal_Int32 nFetchDirection = impl_getPos( g_sPropertyNameForFetchDirection );
450 sal_Int32 nDeleted = 0;
451 if( nFetchSize != -1 )
452 nDeleted++;
453 if( nFetchDirection != -1 )
454 nDeleted++;
456 std::unique_ptr<Sequence< Property > > pOrigProps(new Sequence<Property> ( *m_pProperties ));
457 sal_Int32 nOrigProps = pOrigProps->getLength();
459 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
460 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
462 if( n == nFetchSize || n == nFetchDirection )
463 m--;
464 else
465 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
468 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
469 rMyProp.Name = g_sPropertyNameForFetchSize;
470 rMyProp.Type = cppu::UnoType<sal_Int32>::get();
471 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
473 if( nFetchSize != -1 )
474 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
475 else
476 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
478 rMyProp.Handle = m_nFetchSizePropertyHandle;
482 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
483 rMyProp.Name = g_sPropertyNameForFetchDirection;
484 rMyProp.Type = cppu::UnoType<sal_Bool>::get();
485 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
487 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
491 // XInterface methods.
493 void SAL_CALL CCRS_PropertySetInfo::acquire()
494 throw()
496 OWeakObject::acquire();
499 void SAL_CALL CCRS_PropertySetInfo::release()
500 throw()
502 OWeakObject::release();
505 css::uno::Any SAL_CALL CCRS_PropertySetInfo::queryInterface( const css::uno::Type & rType )
507 css::uno::Any aRet = cppu::queryInterface( rType,
508 static_cast< XTypeProvider* >(this),
509 static_cast< XPropertySetInfo* >(this)
511 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
514 // XTypeProvider methods.
516 //list all interfaces exclusive baseclasses
517 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
518 , XTypeProvider
519 , XPropertySetInfo
522 // XPropertySetInfo methods.
524 //virtual
525 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
526 ::getProperties()
528 return *m_pProperties;
531 //virtual
532 Property SAL_CALL CCRS_PropertySetInfo
533 ::getPropertyByName( const OUString& aName )
535 Property aProp;
536 if ( impl_queryProperty( aName, aProp ) )
537 return aProp;
539 throw UnknownPropertyException(aName);
542 //virtual
543 sal_Bool SAL_CALL CCRS_PropertySetInfo
544 ::hasPropertyByName( const OUString& Name )
546 return ( impl_getPos( Name ) != -1 );
550 // impl_ methods.
553 sal_Int32 CCRS_PropertySetInfo
554 ::impl_getPos( const OUString& rName ) const
556 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
558 const Property& rMyProp = (*m_pProperties)[nN];
559 if( rMyProp.Name == rName )
560 return nN;
562 return -1;
565 bool CCRS_PropertySetInfo
566 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
568 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
570 const Property& rMyProp = (*m_pProperties)[nN];
571 if( rMyProp.Name == rName )
573 rProp.Name = rMyProp.Name;
574 rProp.Handle = rMyProp.Handle;
575 rProp.Type = rMyProp.Type;
576 rProp.Attributes = rMyProp.Attributes;
578 return true;
581 return false;
584 //static
585 bool CCRS_PropertySetInfo
586 ::impl_isMyPropertyName( const OUString& rPropertyName )
588 return ( rPropertyName == g_sPropertyNameForCount
589 || rPropertyName == g_sPropertyNameForFinalCount
590 || rPropertyName == g_sPropertyNameForFetchSize
591 || rPropertyName == g_sPropertyNameForFetchDirection );
594 sal_Int32 CCRS_PropertySetInfo
595 ::impl_getRemainedHandle( ) const
597 sal_Int32 nHandle = 1;
599 if( !m_pProperties )
601 OSL_FAIL( "Properties not initialized yet" );
602 return nHandle;
604 bool bFound = true;
605 while( bFound )
607 bFound = false;
608 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
610 if( nHandle == (*m_pProperties)[nN].Handle )
612 bFound = true;
613 nHandle++;
614 break;
618 return nHandle;
622 // class CachedContentResultSet
625 CachedContentResultSet::CachedContentResultSet(
626 const Reference< XComponentContext > & rxContext
627 , const Reference< XResultSet > & xOrigin
628 , const Reference< XContentIdentifierMapping > &
629 xContentIdentifierMapping )
630 : ContentResultSetWrapper( xOrigin )
632 , m_xContext( rxContext )
634 , m_xContentIdentifierMapping( xContentIdentifierMapping )
635 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
636 , m_bAfterLast( false )
637 , m_nLastAppliedPos( 0 )
638 , m_bAfterLastApplied( false )
639 , m_nKnownCount( 0 )
640 , m_bFinalCount( false )
641 , m_nFetchSize(
642 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
643 , m_nFetchDirection(
644 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
646 , m_bLastReadWasFromCache( false )
647 , m_bLastCachedReadWasNull( true )
648 , m_aCache( m_xContentIdentifierMapping )
649 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
650 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
651 , m_aCacheContent( m_xContentIdentifierMapping )
652 , m_bTriedToGetTypeConverter( false )
654 m_xFetchProvider.set( m_xResultSetOrigin, UNO_QUERY );
655 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
657 m_xFetchProviderForContentAccess.set( m_xResultSetOrigin, UNO_QUERY );
658 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
660 impl_init();
663 CachedContentResultSet::~CachedContentResultSet()
665 impl_deinit();
666 //do not delete m_pMyPropSetInfo, cause it is hold via reference
670 // impl_ methods.
673 bool CachedContentResultSet
674 ::applyPositionToOrigin( sal_Int32 nRow )
676 impl_EnsureNotDisposed();
679 @returns
680 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
681 the result set.
684 osl::ResettableMutexGuard aGuard(m_aMutex);
685 OSL_ENSURE( nRow >= 0, "only positive values supported" );
686 if( !m_xResultSetOrigin.is() )
688 OSL_FAIL( "broadcaster was disposed already" );
689 return false;
691 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
693 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
694 bool bAfterLastApplied = m_bAfterLastApplied;
695 bool bAfterLast = m_bAfterLast;
696 sal_Int32 nForwardOnly = m_nForwardOnly;
698 aGuard.clear();
700 if( bAfterLastApplied || nLastAppliedPos != nRow )
702 if( nForwardOnly == 1 )
704 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
705 throw SQLException();
707 sal_Int32 nN = nRow - nLastAppliedPos;
708 sal_Int32 nM;
709 for( nM = 0; nN--; nM++ )
711 if( !m_xResultSetOrigin->next() )
712 break;
715 aGuard.reset();
716 m_nLastAppliedPos += nM;
717 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
718 return nRow == m_nLastAppliedPos;
721 if( !nRow ) //absolute( 0 ) will throw exception
723 m_xResultSetOrigin->beforeFirst();
725 aGuard.reset();
726 m_nLastAppliedPos = 0;
727 m_bAfterLastApplied = false;
728 return false;
732 //move absolute, if !nLastAppliedPos
733 //because move relative would throw exception
734 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
736 bool bValid = m_xResultSetOrigin->absolute( nRow );
738 aGuard.reset();
739 m_nLastAppliedPos = nRow;
740 m_bAfterLastApplied = !bValid;
741 return bValid;
743 else
745 bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
747 aGuard.reset();
748 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
749 m_bAfterLastApplied = !bValid;
750 return bValid;
753 catch (const SQLException&)
755 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
757 sal_Int32 nN = nRow - nLastAppliedPos;
758 sal_Int32 nM;
759 for( nM = 0; nN--; nM++ )
761 if( !m_xResultSetOrigin->next() )
762 break;
765 aGuard.reset();
766 m_nLastAppliedPos += nM;
767 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
769 else
770 throw;
773 return nRow == m_nLastAppliedPos;
775 return true;
779 //define for fetching data
782 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
783 bool bDirection = !!( \
784 nFetchDirection != FetchDirection::REVERSE ); \
785 FetchResult aResult = \
786 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
787 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
788 aCache.loadData( aResult ); \
789 sal_Int32 nMax = aCache.getMaxRow(); \
790 sal_Int32 nCurCount = m_nKnownCount; \
791 bool bIsFinalCount = aCache.hasKnownLast(); \
792 bool bCurIsFinalCount = m_bFinalCount; \
793 aGuard2.clear(); \
794 if( nMax > nCurCount ) \
795 impl_changeRowCount( nCurCount, nMax ); \
796 if( bIsFinalCount && !bCurIsFinalCount ) \
797 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
799 void CachedContentResultSet
800 ::impl_fetchData( sal_Int32 nRow
801 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
803 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
806 void CachedContentResultSet
807 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
809 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
810 if( nNew <= nOld )
811 return;
813 //create PropertyChangeEvent and set value
814 PropertyChangeEvent aEvt;
816 osl::Guard< osl::Mutex > aGuard( m_aMutex );
817 aEvt.Source = static_cast< XPropertySet * >( this );
818 aEvt.Further = false;
819 aEvt.OldValue <<= nOld;
820 aEvt.NewValue <<= nNew;
822 m_nKnownCount = nNew;
825 //send PropertyChangeEvent to listeners
826 impl_notifyPropertyChangeListeners( aEvt );
829 void CachedContentResultSet
830 ::impl_changeIsRowCountFinal( bool bOld, bool bNew )
832 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
833 if( ! (!bOld && bNew ) )
834 return;
836 //create PropertyChangeEvent and set value
837 PropertyChangeEvent aEvt;
839 osl::Guard< osl::Mutex > aGuard( m_aMutex );
840 aEvt.Source = static_cast< XPropertySet * >( this );
841 aEvt.Further = false;
842 aEvt.OldValue <<= bOld;
843 aEvt.NewValue <<= bNew;
845 m_bFinalCount = bNew;
848 //send PropertyChangeEvent to listeners
849 impl_notifyPropertyChangeListeners( aEvt );
852 bool CachedContentResultSet
853 ::impl_isKnownValidPosition( sal_Int32 nRow )
855 return m_nKnownCount && nRow
856 && nRow <= m_nKnownCount;
859 bool CachedContentResultSet
860 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
862 if( !nRow )
863 return true;
864 if( !m_bFinalCount )
865 return false;
866 return nRow > m_nKnownCount;
870 //virtual
871 void CachedContentResultSet
872 ::impl_initPropertySetInfo()
874 ContentResultSetWrapper::impl_initPropertySetInfo();
876 osl::Guard< osl::Mutex > aGuard( m_aMutex );
877 if( m_xMyPropertySetInfo.is() )
878 return;
879 m_xMyPropertySetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
880 m_xPropertySetInfo = m_xMyPropertySetInfo.get();
884 // XInterface methods.
885 void SAL_CALL CachedContentResultSet::acquire()
886 throw()
888 OWeakObject::acquire();
891 void SAL_CALL CachedContentResultSet::release()
892 throw()
894 OWeakObject::release();
897 Any SAL_CALL CachedContentResultSet
898 ::queryInterface( const Type& rType )
900 //list all interfaces inclusive baseclasses of interfaces
902 Any aRet = ContentResultSetWrapper::queryInterface( rType );
903 if( aRet.hasValue() )
904 return aRet;
906 aRet = cppu::queryInterface( rType,
907 static_cast< XTypeProvider* >( this ),
908 static_cast< XServiceInfo* >( this ) );
910 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
914 // XTypeProvider methods.
916 //list all interfaces exclusive baseclasses
917 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
918 , XTypeProvider
919 , XServiceInfo
920 , XComponent
921 , XCloseable
922 , XResultSetMetaDataSupplier
923 , XPropertySet
925 , XPropertyChangeListener
926 , XVetoableChangeListener
928 , XContentAccess
930 , XResultSet
931 , XRow );
934 // XServiceInfo methods.
936 OUString SAL_CALL CachedContentResultSet::getImplementationName()
938 return "com.sun.star.comp.ucb.CachedContentResultSet";
941 sal_Bool SAL_CALL CachedContentResultSet::supportsService( const OUString& ServiceName )
943 return cppu::supportsService( this, ServiceName );
946 css::uno::Sequence< OUString > SAL_CALL CachedContentResultSet::getSupportedServiceNames()
948 return { CACHED_CONTENT_RESULTSET_SERVICE_NAME };
953 // XPropertySet methods. ( inherited )
956 // virtual
957 void SAL_CALL CachedContentResultSet
958 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
960 impl_EnsureNotDisposed();
962 if( !getPropertySetInfo().is() )
964 OSL_FAIL( "broadcaster was disposed already" );
965 throw UnknownPropertyException();
968 Property aProp = m_xMyPropertySetInfo->getPropertyByName( aPropertyName );
969 //throws UnknownPropertyException, if so
971 if( aProp.Attributes & PropertyAttribute::READONLY )
973 //It is assumed, that the properties
974 //'RowCount' and 'IsRowCountFinal' are readonly!
975 throw IllegalArgumentException();
977 if( aProp.Name == g_sPropertyNameForFetchDirection )
979 //check value
980 sal_Int32 nNew;
981 if( !( aValue >>= nNew ) )
983 throw IllegalArgumentException();
986 if( nNew == FetchDirection::UNKNOWN )
988 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
990 else if( !( nNew == FetchDirection::FORWARD
991 || nNew == FetchDirection::REVERSE ) )
993 throw IllegalArgumentException();
996 //create PropertyChangeEvent and set value
997 PropertyChangeEvent aEvt;
999 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1000 aEvt.Source = static_cast< XPropertySet * >( this );
1001 aEvt.PropertyName = aPropertyName;
1002 aEvt.Further = false;
1003 aEvt.PropertyHandle = m_xMyPropertySetInfo->
1004 m_nFetchDirectionPropertyHandle;
1005 aEvt.OldValue <<= m_nFetchDirection;
1006 aEvt.NewValue <<= nNew;
1008 m_nFetchDirection = nNew;
1011 //send PropertyChangeEvent to listeners
1012 impl_notifyPropertyChangeListeners( aEvt );
1014 else if( aProp.Name == g_sPropertyNameForFetchSize )
1016 //check value
1017 sal_Int32 nNew;
1018 if( !( aValue >>= nNew ) )
1020 throw IllegalArgumentException();
1023 if( nNew < 0 )
1025 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1028 //create PropertyChangeEvent and set value
1029 PropertyChangeEvent aEvt;
1031 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1032 aEvt.Source = static_cast< XPropertySet * >( this );
1033 aEvt.PropertyName = aPropertyName;
1034 aEvt.Further = false;
1035 aEvt.PropertyHandle = m_xMyPropertySetInfo->
1036 m_nFetchSizePropertyHandle;
1037 aEvt.OldValue <<= m_nFetchSize;
1038 aEvt.NewValue <<= nNew;
1040 m_nFetchSize = nNew;
1043 //send PropertyChangeEvent to listeners
1044 impl_notifyPropertyChangeListeners( aEvt );
1046 else
1048 impl_init_xPropertySetOrigin();
1050 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1051 if( !m_xPropertySetOrigin.is() )
1053 OSL_FAIL( "broadcaster was disposed already" );
1054 return;
1057 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1062 // virtual
1063 Any SAL_CALL CachedContentResultSet
1064 ::getPropertyValue( const OUString& rPropertyName )
1066 impl_EnsureNotDisposed();
1068 if( !getPropertySetInfo().is() )
1070 OSL_FAIL( "broadcaster was disposed already" );
1071 throw UnknownPropertyException();
1074 m_xMyPropertySetInfo->getPropertyByName( rPropertyName );
1075 //throws UnknownPropertyException, if so
1077 Any aValue;
1078 if( rPropertyName == g_sPropertyNameForCount )
1080 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1081 aValue <<= m_nKnownCount;
1083 else if( rPropertyName == g_sPropertyNameForFinalCount )
1085 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1086 aValue <<= m_bFinalCount;
1088 else if( rPropertyName == g_sPropertyNameForFetchSize )
1090 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1091 aValue <<= m_nFetchSize;
1093 else if( rPropertyName == g_sPropertyNameForFetchDirection )
1095 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1096 aValue <<= m_nFetchDirection;
1098 else
1100 impl_init_xPropertySetOrigin();
1102 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1103 if( !m_xPropertySetOrigin.is() )
1105 OSL_FAIL( "broadcaster was disposed already" );
1106 throw UnknownPropertyException();
1109 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1111 return aValue;
1115 // own methods. ( inherited )
1118 //virtual
1119 void CachedContentResultSet
1120 ::impl_disposing( const EventObject& rEventObject )
1123 impl_EnsureNotDisposed();
1124 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1125 //release all references to the broadcaster:
1126 m_xFetchProvider.clear();
1127 m_xFetchProviderForContentAccess.clear();
1129 ContentResultSetWrapper::impl_disposing( rEventObject );
1132 //virtual
1133 void CachedContentResultSet
1134 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1136 impl_EnsureNotDisposed();
1138 PropertyChangeEvent aEvt( rEvt );
1139 aEvt.Source = static_cast< XPropertySet * >( this );
1140 aEvt.Further = false;
1143 if( CCRS_PropertySetInfo
1144 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1146 //don't notify foreign events on fetchsize and fetchdirection
1147 if( aEvt.PropertyName == g_sPropertyNameForFetchSize
1148 || aEvt.PropertyName == g_sPropertyNameForFetchDirection )
1149 return;
1151 //adjust my props 'RowCount' and 'IsRowCountFinal'
1152 if( aEvt.PropertyName == g_sPropertyNameForCount )
1153 {//RowCount changed
1155 //check value
1156 sal_Int32 nNew = 0;
1157 if( !( aEvt.NewValue >>= nNew ) )
1159 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1160 return;
1163 impl_changeRowCount( m_nKnownCount, nNew );
1165 else if( aEvt.PropertyName == g_sPropertyNameForFinalCount )
1166 {//IsRowCountFinal changed
1168 //check value
1169 bool bNew = false;
1170 if( !( aEvt.NewValue >>= bNew ) )
1172 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1173 return;
1175 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1177 return;
1181 impl_notifyPropertyChangeListeners( aEvt );
1185 //virtual
1186 void CachedContentResultSet
1187 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1189 impl_EnsureNotDisposed();
1191 //don't notify events on my properties, cause they are not vetoable
1192 if( CCRS_PropertySetInfo
1193 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1195 return;
1199 PropertyChangeEvent aEvt( rEvt );
1200 aEvt.Source = static_cast< XPropertySet * >( this );
1201 aEvt.Further = false;
1203 impl_notifyVetoableChangeListeners( aEvt );
1207 // XContentAccess methods. ( inherited ) ( -- position dependent )
1210 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1211 impl_EnsureNotDisposed(); \
1212 osl::ResettableMutexGuard aGuard(m_aMutex); \
1213 sal_Int32 nRow = m_nRow; \
1214 sal_Int32 nFetchSize = m_nFetchSize; \
1215 sal_Int32 nFetchDirection = m_nFetchDirection; \
1216 if( !m_aCache##XXX.hasRow( nRow ) ) \
1218 try \
1220 bool isCleared = false; \
1221 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1223 if( !m_xFetchProviderForContentAccess.is() ) \
1225 OSL_FAIL( "broadcaster was disposed already" ); \
1226 throw RuntimeException(); \
1228 aGuard.clear(); \
1229 isCleared = true; \
1230 if( impl_isForwardOnly() ) \
1231 applyPositionToOrigin( nRow ); \
1233 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1235 if (isCleared) \
1237 aGuard.reset(); \
1239 if( !m_aCache##XXX.hasRow( nRow ) ) \
1241 aGuard.clear(); \
1242 applyPositionToOrigin( nRow ); \
1243 TYPE aRet = ContentResultSetWrapper::queryXXX();\
1244 if( m_xContentIdentifierMapping.is() ) \
1245 return m_xContentIdentifierMapping->map##XXX( aRet );\
1246 return aRet; \
1249 catch (const RuntimeException&) \
1251 throw; \
1253 catch (const Exception& e) \
1255 Any a(cppu::getCaughtException()); \
1256 throw WrappedTargetRuntimeException( \
1257 "wrapped Exception " + e.Message, \
1258 Reference<XInterface>(), a); \
1261 return m_aCache##XXX.get##XXX( nRow );
1263 // virtual
1264 OUString SAL_CALL CachedContentResultSet
1265 ::queryContentIdentifierString()
1267 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1271 // virtual
1272 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1273 ::queryContentIdentifier()
1275 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1279 // virtual
1280 Reference< XContent > SAL_CALL CachedContentResultSet
1281 ::queryContent()
1283 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1287 // XResultSet methods. ( inherited )
1289 //virtual
1291 sal_Bool SAL_CALL CachedContentResultSet
1292 ::next()
1294 impl_EnsureNotDisposed();
1296 osl::ResettableMutexGuard aGuard(m_aMutex);
1297 //after last
1298 if( m_bAfterLast )
1299 return false;
1300 //last
1301 aGuard.clear();
1302 if( isLast() )
1304 aGuard.reset();
1305 m_nRow++;
1306 m_bAfterLast = true;
1307 return false;
1309 aGuard.reset();
1310 //known valid position
1311 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1313 m_nRow++;
1314 return true;
1317 //unknown position
1318 sal_Int32 nRow = m_nRow;
1319 aGuard.clear();
1321 bool bValid = applyPositionToOrigin( nRow + 1 );
1323 aGuard.reset();
1324 m_nRow = nRow + 1;
1325 m_bAfterLast = !bValid;
1326 return bValid;
1329 //virtual
1330 sal_Bool SAL_CALL CachedContentResultSet
1331 ::previous()
1333 impl_EnsureNotDisposed();
1335 if( impl_isForwardOnly() )
1336 throw SQLException();
1338 osl::ResettableMutexGuard aGuard(m_aMutex);
1339 //before first ?:
1340 if( !m_bAfterLast && !m_nRow )
1341 return false;
1342 //first ?:
1343 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1345 m_nRow--;
1346 m_bAfterLast = false;
1347 return false;
1349 //known valid position ?:
1350 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1352 m_nRow--;
1353 m_bAfterLast = false;
1354 return true;
1356 //unknown position:
1357 sal_Int32 nRow = m_nRow;
1358 aGuard.clear();
1360 bool bValid = applyPositionToOrigin( nRow - 1 );
1362 aGuard.reset();
1363 m_nRow = nRow - 1;
1364 m_bAfterLast = false;
1365 return bValid;
1368 //virtual
1369 sal_Bool SAL_CALL CachedContentResultSet
1370 ::absolute( sal_Int32 row )
1372 impl_EnsureNotDisposed();
1374 if( !row )
1375 throw SQLException();
1377 if( impl_isForwardOnly() )
1378 throw SQLException();
1380 osl::ResettableMutexGuard aGuard(m_aMutex);
1382 if( !m_xResultSetOrigin.is() )
1384 OSL_FAIL( "broadcaster was disposed already" );
1385 return false;
1387 if( row < 0 )
1389 if( m_bFinalCount )
1391 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1392 bool bValid = true;
1393 if( nNewRow <= 0 )
1395 nNewRow = 0;
1396 bValid = false;
1398 m_nRow = nNewRow;
1399 m_bAfterLast = false;
1400 return bValid;
1402 //unknown final count:
1403 aGuard.clear();
1405 bool bValid = m_xResultSetOrigin->absolute( row );
1407 aGuard.reset();
1408 if( m_bFinalCount )
1410 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1411 if( nNewRow < 0 )
1412 nNewRow = 0;
1413 m_nLastAppliedPos = nNewRow;
1414 m_nRow = nNewRow;
1415 m_bAfterLastApplied = m_bAfterLast = false;
1416 return bValid;
1418 aGuard.clear();
1420 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1422 aGuard.reset();
1423 m_nLastAppliedPos = nCurRow;
1424 m_nRow = nCurRow;
1425 m_bAfterLast = false;
1426 return nCurRow != 0;
1428 //row > 0:
1429 if( m_bFinalCount )
1431 if( row > m_nKnownCount )
1433 m_nRow = m_nKnownCount + 1;
1434 m_bAfterLast = true;
1435 return false;
1437 m_nRow = row;
1438 m_bAfterLast = false;
1439 return true;
1441 //unknown new position:
1442 aGuard.clear();
1444 bool bValid = m_xResultSetOrigin->absolute( row );
1446 aGuard.reset();
1447 if( m_bFinalCount )
1449 sal_Int32 nNewRow = row;
1450 if( nNewRow > m_nKnownCount )
1452 nNewRow = m_nKnownCount + 1;
1453 m_bAfterLastApplied = m_bAfterLast = true;
1455 else
1456 m_bAfterLastApplied = m_bAfterLast = false;
1458 m_nLastAppliedPos = nNewRow;
1459 m_nRow = nNewRow;
1460 return bValid;
1462 aGuard.clear();
1464 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1465 bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1467 aGuard.reset();
1468 m_nLastAppliedPos = nCurRow;
1469 m_nRow = nCurRow;
1470 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1471 return nCurRow && !bIsAfterLast;
1474 //virtual
1475 sal_Bool SAL_CALL CachedContentResultSet
1476 ::relative( sal_Int32 rows )
1478 impl_EnsureNotDisposed();
1480 if( impl_isForwardOnly() )
1481 throw SQLException();
1483 osl::ResettableMutexGuard aGuard(m_aMutex);
1484 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1485 throw SQLException();
1487 if( !rows )
1488 return true;
1490 sal_Int32 nNewRow = m_nRow + rows;
1491 if( nNewRow < 0 )
1492 nNewRow = 0;
1494 if( impl_isKnownValidPosition( nNewRow ) )
1496 m_nRow = nNewRow;
1497 m_bAfterLast = false;
1498 return true;
1500 else
1502 //known invalid new position:
1503 if( nNewRow == 0 )
1505 m_bAfterLast = false;
1506 m_nRow = 0;
1507 return false;
1509 if( m_bFinalCount && nNewRow > m_nKnownCount )
1511 m_bAfterLast = true;
1512 m_nRow = m_nKnownCount + 1;
1513 return false;
1515 //unknown new position:
1516 aGuard.clear();
1517 bool bValid = applyPositionToOrigin( nNewRow );
1519 aGuard.reset();
1520 m_nRow = nNewRow;
1521 m_bAfterLast = !bValid; // only nNewRow > 0 possible here
1522 return bValid;
1527 //virtual
1528 sal_Bool SAL_CALL CachedContentResultSet
1529 ::first()
1531 impl_EnsureNotDisposed();
1533 if( impl_isForwardOnly() )
1534 throw SQLException();
1536 osl::ResettableMutexGuard aGuard(m_aMutex);
1537 if( impl_isKnownValidPosition( 1 ) )
1539 m_nRow = 1;
1540 m_bAfterLast = false;
1541 return true;
1543 if( impl_isKnownInvalidPosition( 1 ) )
1545 m_nRow = 1;
1546 m_bAfterLast = false;
1547 return false;
1549 //unknown position
1550 aGuard.clear();
1552 bool bValid = applyPositionToOrigin( 1 );
1554 aGuard.reset();
1555 m_nRow = 1;
1556 m_bAfterLast = false;
1557 return bValid;
1560 //virtual
1561 sal_Bool SAL_CALL CachedContentResultSet
1562 ::last()
1564 impl_EnsureNotDisposed();
1566 if( impl_isForwardOnly() )
1567 throw SQLException();
1569 osl::ResettableMutexGuard aGuard(m_aMutex);
1570 if( m_bFinalCount )
1572 m_nRow = m_nKnownCount;
1573 m_bAfterLast = false;
1574 return m_nKnownCount != 0;
1576 //unknown position
1577 if( !m_xResultSetOrigin.is() )
1579 OSL_FAIL( "broadcaster was disposed already" );
1580 return false;
1582 aGuard.clear();
1584 bool bValid = m_xResultSetOrigin->last();
1586 aGuard.reset();
1587 m_bAfterLastApplied = m_bAfterLast = false;
1588 if( m_bFinalCount )
1590 m_nLastAppliedPos = m_nKnownCount;
1591 m_nRow = m_nKnownCount;
1592 return bValid;
1594 aGuard.clear();
1596 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1598 aGuard.reset();
1599 m_nLastAppliedPos = nCurRow;
1600 m_nRow = nCurRow;
1601 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1602 m_nKnownCount = nCurRow;
1603 m_bFinalCount = true;
1604 return nCurRow != 0;
1607 //virtual
1608 void SAL_CALL CachedContentResultSet
1609 ::beforeFirst()
1611 impl_EnsureNotDisposed();
1613 if( impl_isForwardOnly() )
1614 throw SQLException();
1616 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1617 m_nRow = 0;
1618 m_bAfterLast = false;
1621 //virtual
1622 void SAL_CALL CachedContentResultSet
1623 ::afterLast()
1625 impl_EnsureNotDisposed();
1627 if( impl_isForwardOnly() )
1628 throw SQLException();
1630 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1631 m_nRow = 1;
1632 m_bAfterLast = true;
1635 //virtual
1636 sal_Bool SAL_CALL CachedContentResultSet
1637 ::isAfterLast()
1639 impl_EnsureNotDisposed();
1641 osl::ResettableMutexGuard aGuard(m_aMutex);
1642 if( !m_bAfterLast )
1643 return false;
1644 if( m_nKnownCount )
1645 return m_bAfterLast;
1646 if( m_bFinalCount )
1647 return false;
1649 if( !m_xResultSetOrigin.is() )
1651 OSL_FAIL( "broadcaster was disposed already" );
1652 return false;
1654 aGuard.clear();
1656 //find out whether the original resultset contains rows or not
1657 m_xResultSetOrigin->afterLast();
1659 aGuard.reset();
1660 m_bAfterLastApplied = true;
1661 aGuard.clear();
1663 return m_xResultSetOrigin->isAfterLast();
1666 //virtual
1667 sal_Bool SAL_CALL CachedContentResultSet
1668 ::isBeforeFirst()
1670 impl_EnsureNotDisposed();
1672 osl::ResettableMutexGuard aGuard(m_aMutex);
1673 if( m_bAfterLast )
1674 return false;
1675 if( m_nRow )
1676 return false;
1677 if( m_nKnownCount )
1678 return true;
1679 if( m_bFinalCount )
1680 return false;
1682 if( !m_xResultSetOrigin.is() )
1684 OSL_FAIL( "broadcaster was disposed already" );
1685 return false;
1687 aGuard.clear();
1689 //find out whether the original resultset contains rows or not
1690 m_xResultSetOrigin->beforeFirst();
1692 aGuard.reset();
1693 m_bAfterLastApplied = false;
1694 m_nLastAppliedPos = 0;
1695 aGuard.clear();
1697 return m_xResultSetOrigin->isBeforeFirst();
1700 //virtual
1701 sal_Bool SAL_CALL CachedContentResultSet
1702 ::isFirst()
1704 impl_EnsureNotDisposed();
1706 sal_Int32 nRow = 0;
1707 Reference< XResultSet > xResultSetOrigin;
1710 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1711 if( m_bAfterLast )
1712 return false;
1713 if( m_nRow != 1 )
1714 return false;
1715 if( m_nKnownCount )
1716 return true;
1717 if( m_bFinalCount )
1718 return false;
1720 nRow = m_nRow;
1721 xResultSetOrigin = m_xResultSetOrigin;
1724 //need to ask origin
1726 if( applyPositionToOrigin( nRow ) )
1727 return xResultSetOrigin->isFirst();
1728 else
1729 return false;
1733 //virtual
1734 sal_Bool SAL_CALL CachedContentResultSet
1735 ::isLast()
1737 impl_EnsureNotDisposed();
1739 sal_Int32 nRow = 0;
1740 Reference< XResultSet > xResultSetOrigin;
1742 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1743 if( m_bAfterLast )
1744 return false;
1745 if( m_nRow < m_nKnownCount )
1746 return false;
1747 if( m_bFinalCount )
1748 return m_nKnownCount && m_nRow == m_nKnownCount;
1750 nRow = m_nRow;
1751 xResultSetOrigin = m_xResultSetOrigin;
1754 //need to ask origin
1756 if( applyPositionToOrigin( nRow ) )
1757 return xResultSetOrigin->isLast();
1758 else
1759 return false;
1764 //virtual
1765 sal_Int32 SAL_CALL CachedContentResultSet
1766 ::getRow()
1768 impl_EnsureNotDisposed();
1770 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1771 if( m_bAfterLast )
1772 return 0;
1773 return m_nRow;
1776 //virtual
1777 void SAL_CALL CachedContentResultSet
1778 ::refreshRow()
1780 impl_EnsureNotDisposed();
1782 //the ContentResultSet is static and will not change
1783 //therefore we don't need to reload anything
1786 //virtual
1787 sal_Bool SAL_CALL CachedContentResultSet
1788 ::rowUpdated()
1790 impl_EnsureNotDisposed();
1792 //the ContentResultSet is static and will not change
1793 return false;
1795 //virtual
1796 sal_Bool SAL_CALL CachedContentResultSet
1797 ::rowInserted()
1799 impl_EnsureNotDisposed();
1801 //the ContentResultSet is static and will not change
1802 return false;
1805 //virtual
1806 sal_Bool SAL_CALL CachedContentResultSet
1807 ::rowDeleted()
1809 impl_EnsureNotDisposed();
1811 //the ContentResultSet is static and will not change
1812 return false;
1815 //virtual
1816 Reference< XInterface > SAL_CALL CachedContentResultSet
1817 ::getStatement()
1819 impl_EnsureNotDisposed();
1820 //@todo ?return anything
1821 return Reference< XInterface >();
1825 // XRow methods. ( inherited )
1828 //virtual
1829 sal_Bool SAL_CALL CachedContentResultSet
1830 ::wasNull()
1832 impl_EnsureNotDisposed();
1833 impl_init_xRowOrigin();
1835 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1836 if( m_bLastReadWasFromCache )
1837 return m_bLastCachedReadWasNull;
1838 if( !m_xRowOrigin.is() )
1840 OSL_FAIL( "broadcaster was disposed already" );
1841 return false;
1844 return m_xRowOrigin->wasNull();
1847 //virtual
1848 OUString SAL_CALL CachedContentResultSet
1849 ::getString( sal_Int32 columnIndex )
1851 return rowOriginGet<OUString>(&css::sdbc::XRow::getString, columnIndex);
1854 //virtual
1855 sal_Bool SAL_CALL CachedContentResultSet
1856 ::getBoolean( sal_Int32 columnIndex )
1858 return rowOriginGet<sal_Bool>(&css::sdbc::XRow::getBoolean, columnIndex);
1861 //virtual
1862 sal_Int8 SAL_CALL CachedContentResultSet
1863 ::getByte( sal_Int32 columnIndex )
1865 return rowOriginGet<sal_Int8>(&css::sdbc::XRow::getByte, columnIndex);
1868 //virtual
1869 sal_Int16 SAL_CALL CachedContentResultSet
1870 ::getShort( sal_Int32 columnIndex )
1872 return rowOriginGet<sal_Int16>(&css::sdbc::XRow::getShort, columnIndex);
1875 //virtual
1876 sal_Int32 SAL_CALL CachedContentResultSet
1877 ::getInt( sal_Int32 columnIndex )
1879 return rowOriginGet<sal_Int32>(&css::sdbc::XRow::getInt, columnIndex);
1882 //virtual
1883 sal_Int64 SAL_CALL CachedContentResultSet
1884 ::getLong( sal_Int32 columnIndex )
1886 return rowOriginGet<sal_Int64>(&css::sdbc::XRow::getLong, columnIndex);
1889 //virtual
1890 float SAL_CALL CachedContentResultSet
1891 ::getFloat( sal_Int32 columnIndex )
1893 return rowOriginGet<float>(&css::sdbc::XRow::getFloat, columnIndex);
1896 //virtual
1897 double SAL_CALL CachedContentResultSet
1898 ::getDouble( sal_Int32 columnIndex )
1900 return rowOriginGet<double>(&css::sdbc::XRow::getDouble, columnIndex);
1903 //virtual
1904 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
1905 ::getBytes( sal_Int32 columnIndex )
1907 return rowOriginGet< css::uno::Sequence<sal_Int8> >(
1908 &css::sdbc::XRow::getBytes, columnIndex);
1911 //virtual
1912 Date SAL_CALL CachedContentResultSet
1913 ::getDate( sal_Int32 columnIndex )
1915 return rowOriginGet<css::util::Date>(
1916 &css::sdbc::XRow::getDate, columnIndex);
1919 //virtual
1920 Time SAL_CALL CachedContentResultSet
1921 ::getTime( sal_Int32 columnIndex )
1923 return rowOriginGet<css::util::Time>(
1924 &css::sdbc::XRow::getTime, columnIndex);
1927 //virtual
1928 DateTime SAL_CALL CachedContentResultSet
1929 ::getTimestamp( sal_Int32 columnIndex )
1931 return rowOriginGet<css::util::DateTime>(
1932 &css::sdbc::XRow::getTimestamp, columnIndex);
1935 //virtual
1936 Reference< css::io::XInputStream >
1937 SAL_CALL CachedContentResultSet
1938 ::getBinaryStream( sal_Int32 columnIndex )
1940 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
1941 &css::sdbc::XRow::getBinaryStream, columnIndex);
1944 //virtual
1945 Reference< css::io::XInputStream >
1946 SAL_CALL CachedContentResultSet
1947 ::getCharacterStream( sal_Int32 columnIndex )
1949 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
1950 &css::sdbc::XRow::getCharacterStream, columnIndex);
1953 //virtual
1954 Any SAL_CALL CachedContentResultSet
1955 ::getObject( sal_Int32 columnIndex,
1956 const Reference<
1957 css::container::XNameAccess >& typeMap )
1959 //if you change this function please pay attention to
1960 //function template rowOriginGet, where this is similar implemented
1962 osl::ResettableMutexGuard aGuard(m_aMutex);
1963 sal_Int32 nRow = m_nRow;
1964 sal_Int32 nFetchSize = m_nFetchSize;
1965 sal_Int32 nFetchDirection = m_nFetchDirection;
1966 if( !m_aCache.hasRow( nRow ) )
1968 bool isCleared = false;
1969 if( !m_aCache.hasCausedException( nRow ) )
1971 if( !m_xFetchProvider.is() )
1973 OSL_FAIL( "broadcaster was disposed already" );
1974 return Any();
1976 isCleared = true;
1977 aGuard.clear();
1979 impl_fetchData( nRow, nFetchSize, nFetchDirection );
1981 if (isCleared)
1983 aGuard.reset();
1985 if( !m_aCache.hasRow( nRow ) )
1987 m_bLastReadWasFromCache = false;
1988 aGuard.clear();
1989 applyPositionToOrigin( nRow );
1990 impl_init_xRowOrigin();
1991 return m_xRowOrigin->getObject( columnIndex, typeMap );
1994 //@todo: pay attention to typeMap
1995 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
1996 m_bLastReadWasFromCache = true;
1997 m_bLastCachedReadWasNull = !rValue.hasValue();
1998 return rValue;
2001 //virtual
2002 Reference< XRef > SAL_CALL CachedContentResultSet
2003 ::getRef( sal_Int32 columnIndex )
2005 return rowOriginGet< css::uno::Reference<css::sdbc::XRef> >(
2006 &css::sdbc::XRow::getRef, columnIndex);
2009 //virtual
2010 Reference< XBlob > SAL_CALL CachedContentResultSet
2011 ::getBlob( sal_Int32 columnIndex )
2013 return rowOriginGet< css::uno::Reference<css::sdbc::XBlob> >(
2014 &css::sdbc::XRow::getBlob, columnIndex);
2017 //virtual
2018 Reference< XClob > SAL_CALL CachedContentResultSet
2019 ::getClob( sal_Int32 columnIndex )
2021 return rowOriginGet< css::uno::Reference<css::sdbc::XClob> >(
2022 &css::sdbc::XRow::getClob, columnIndex);
2025 //virtual
2026 Reference< XArray > SAL_CALL CachedContentResultSet
2027 ::getArray( sal_Int32 columnIndex )
2029 return rowOriginGet< css::uno::Reference<css::sdbc::XArray> >(
2030 &css::sdbc::XRow::getArray, columnIndex);
2034 // Type Converter Support
2037 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2039 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2041 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2043 m_bTriedToGetTypeConverter = true;
2044 m_xTypeConverter.set( Converter::create(m_xContext) );
2046 OSL_ENSURE( m_xTypeConverter.is(),
2047 "PropertyValueSet::getTypeConverter() - "
2048 "Service 'com.sun.star.script.Converter' n/a!" );
2050 return m_xTypeConverter;
2054 // class CachedContentResultSetFactory
2057 CachedContentResultSetFactory::CachedContentResultSetFactory(
2058 const Reference< XComponentContext > & rxContext )
2060 m_xContext = rxContext;
2063 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2067 // CachedContentResultSetFactory XServiceInfo methods.
2069 XSERVICEINFO_COMMOM_IMPL( CachedContentResultSetFactory,
2070 "com.sun.star.comp.ucb.CachedContentResultSetFactory" )
2071 /// @throws css::uno::Exception
2072 static css::uno::Reference< css::uno::XInterface >
2073 CachedContentResultSetFactory_CreateInstance( const css::uno::Reference< css::lang::XMultiServiceFactory> & rSMgr )
2075 css::lang::XServiceInfo* pX = new CachedContentResultSetFactory( ucbhelper::getComponentContext(rSMgr) );
2076 return css::uno::Reference< css::uno::XInterface >::query( pX );
2079 css::uno::Sequence< OUString >
2080 CachedContentResultSetFactory::getSupportedServiceNames_Static()
2082 css::uno::Sequence< OUString > aSNS { CACHED_CONTENT_RESULTSET_FACTORY_NAME };
2083 return aSNS;
2086 // Service factory implementation.
2089 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2092 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2095 //virtual
2096 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2097 ::createCachedContentResultSet(
2098 const Reference< XResultSet > & xSource,
2099 const Reference< XContentIdentifierMapping > & xMapping )
2101 Reference< XResultSet > xRet = new CachedContentResultSet( m_xContext, xSource, xMapping );
2102 return xRet;
2105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */