nss: upgrade to release 3.73
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blob483b7e3fcb740c7c34b78fadc594b05764d00715
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/macros.hxx>
35 #include <memory>
37 using namespace com::sun::star::beans;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::script;
40 using namespace com::sun::star::sdbc;
41 using namespace com::sun::star::ucb;
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::util;
44 using namespace cppu;
47 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
48 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
50 //if you change this function template please pay attention to
51 //function getObject, where this is similar implemented
53 template<typename T> T CachedContentResultSet::rowOriginGet(
54 T (SAL_CALL css::sdbc::XRow::* f)(sal_Int32), sal_Int32 columnIndex)
56 impl_EnsureNotDisposed();
57 osl::ResettableMutexGuard aGuard(m_aMutex);
58 sal_Int32 nRow = m_nRow;
59 sal_Int32 nFetchSize = m_nFetchSize;
60 sal_Int32 nFetchDirection = m_nFetchDirection;
61 if( !m_aCache.hasRow( nRow ) )
63 bool isCleared = false;
64 if( !m_aCache.hasCausedException( nRow ) )
66 if( !m_xFetchProvider.is() )
68 OSL_FAIL( "broadcaster was disposed already" );
69 throw SQLException();
71 aGuard.clear();
72 isCleared = true;
73 if( impl_isForwardOnly() )
74 applyPositionToOrigin( nRow );
76 impl_fetchData( nRow, nFetchSize, nFetchDirection );
78 if (isCleared)
80 aGuard.reset();
82 if( !m_aCache.hasRow( nRow ) )
84 m_bLastReadWasFromCache = false;
85 aGuard.clear();
86 applyPositionToOrigin( nRow );
87 impl_init_xRowOrigin();
88 return (m_xRowOrigin.get()->*f)( columnIndex );
91 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
92 T aRet = T();
93 m_bLastReadWasFromCache = true;
94 m_bLastCachedReadWasNull = !( rValue >>= aRet );
95 /* Last chance. Try type converter service... */
96 if ( m_bLastCachedReadWasNull && rValue.hasValue() )
98 Reference< XTypeConverter > xConverter = getTypeConverter();
99 if ( xConverter.is() )
103 Any aConvAny = xConverter->convertTo(
104 rValue,
105 cppu::UnoType<T>::get() );
106 m_bLastCachedReadWasNull = !( aConvAny >>= aRet );
108 catch (const IllegalArgumentException&)
111 catch (const CannotConvertException&)
116 return aRet;
120 // CCRS_Cache methods
123 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
124 const Reference< XContentIdentifierMapping > & xMapping )
125 : m_xContentIdentifierMapping( xMapping )
129 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
133 void CachedContentResultSet::CCRS_Cache
134 ::clear()
136 m_pResult.reset();
137 m_pMappedReminder.reset();
140 void CachedContentResultSet::CCRS_Cache
141 ::loadData( const FetchResult& rResult )
143 clear();
144 m_pResult.reset( new FetchResult( rResult ) );
147 bool CachedContentResultSet::CCRS_Cache
148 ::hasRow( sal_Int32 row )
150 if( !m_pResult )
151 return false;
152 sal_Int32 nStart = m_pResult->StartIndex;
153 sal_Int32 nEnd = nStart;
154 if( m_pResult->Orientation )
155 nEnd += m_pResult->Rows.getLength() - 1;
156 else
157 nStart -= m_pResult->Rows.getLength() + 1;
159 return nStart <= row && row <= nEnd;
162 sal_Int32 CachedContentResultSet::CCRS_Cache
163 ::getMaxRow() const
165 if( !m_pResult )
166 return 0;
167 sal_Int32 nEnd = m_pResult->StartIndex;
168 if( m_pResult->Orientation )
169 return nEnd + m_pResult->Rows.getLength() - 1;
170 else
171 return nEnd;
174 bool CachedContentResultSet::CCRS_Cache
175 ::hasKnownLast() const
177 if( !m_pResult )
178 return false;
180 return ( m_pResult->FetchError & FetchError::ENDOFDATA )
181 && m_pResult->Orientation
182 && m_pResult->Rows.hasElements();
185 bool CachedContentResultSet::CCRS_Cache
186 ::hasCausedException( sal_Int32 nRow )
188 if( !m_pResult )
189 return false;
190 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
191 return false;
193 sal_Int32 nEnd = m_pResult->StartIndex;
194 if( m_pResult->Orientation )
195 nEnd += m_pResult->Rows.getLength();
197 return nRow == nEnd+1;
200 Any& CachedContentResultSet::CCRS_Cache
201 ::getRowAny( sal_Int32 nRow )
203 if( !nRow )
204 throw SQLException();
205 if( !m_pResult )
206 throw SQLException();
207 if( !hasRow( nRow ) )
208 throw SQLException();
210 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
211 if( nDiff < 0 )
212 nDiff *= -1;
214 return (m_pResult->Rows)[nDiff];
217 void CachedContentResultSet::CCRS_Cache
218 ::remindMapped( sal_Int32 nRow )
220 //remind that this row was mapped
221 if( !m_pResult )
222 return;
223 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
224 if( nDiff < 0 )
225 nDiff *= -1;
226 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
227 if( nDiff < pMappedReminder->getLength() )
228 (*pMappedReminder)[nDiff] = true;
231 bool CachedContentResultSet::CCRS_Cache
232 ::isRowMapped( sal_Int32 nRow )
234 if( !m_pMappedReminder || !m_pResult )
235 return false;
236 sal_Int32 nDiff = nRow - m_pResult->StartIndex;
237 if( nDiff < 0 )
238 nDiff *= -1;
239 if( nDiff < m_pMappedReminder->getLength() )
240 return (*m_pMappedReminder)[nDiff];
241 return false;
244 Sequence< sal_Bool >* CachedContentResultSet::CCRS_Cache
245 ::getMappedReminder()
247 if( !m_pMappedReminder )
249 sal_Int32 nCount = m_pResult->Rows.getLength();
250 m_pMappedReminder.reset(new Sequence< sal_Bool >( nCount ));
251 std::fill(m_pMappedReminder->begin(), m_pMappedReminder->end(), false);
253 return m_pMappedReminder.get();
256 const Any& CachedContentResultSet::CCRS_Cache
257 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
259 if( !nColumnIndex )
260 throw SQLException();
261 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
263 Any& rRow = getRowAny( nRow );
264 Sequence< Any > aValue;
265 rRow >>= aValue;
266 if( m_xContentIdentifierMapping->mapRow( aValue ) )
268 rRow <<= aValue;
269 remindMapped( nRow );
271 else
272 m_xContentIdentifierMapping.clear();
274 auto & rowAny = getRowAny(nRow);
275 auto rRow = o3tl::doAccess<Sequence<Any>>(rowAny);
277 if( nColumnIndex > rRow->getLength() )
278 throw SQLException();
279 return (*rRow)[nColumnIndex-1];
282 OUString const & CachedContentResultSet::CCRS_Cache
283 ::getContentIdentifierString( sal_Int32 nRow )
287 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
289 Any& rRow = getRowAny( nRow );
290 OUString aValue;
291 rRow >>= aValue;
292 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
293 remindMapped( nRow );
295 return *o3tl::doAccess<OUString>(getRowAny(nRow));
297 catch(const SQLException& ex)
299 css::uno::Any anyEx = cppu::getCaughtException();
300 throw css::lang::WrappedTargetRuntimeException( ex.Message,
301 css::uno::Reference< css::uno::XInterface >(),
302 anyEx );
306 Reference< XContentIdentifier > CachedContentResultSet::CCRS_Cache
307 ::getContentIdentifier( sal_Int32 nRow )
311 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
313 Any& rRow = getRowAny( nRow );
314 Reference< XContentIdentifier > aValue;
315 rRow >>= aValue;
316 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
317 remindMapped( nRow );
319 return *o3tl::doAccess<Reference<XContentIdentifier>>(getRowAny(nRow));
321 catch(const SQLException& ex)
323 css::uno::Any anyEx = cppu::getCaughtException();
324 throw css::lang::WrappedTargetRuntimeException( ex.Message,
325 css::uno::Reference< css::uno::XInterface >(),
326 anyEx );
330 Reference< XContent > CachedContentResultSet::CCRS_Cache
331 ::getContent( sal_Int32 nRow )
335 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
337 Any& rRow = getRowAny( nRow );
338 Reference< XContent > aValue;
339 rRow >>= aValue;
340 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
341 remindMapped( nRow );
343 return *o3tl::doAccess<Reference<XContent>>(getRowAny(nRow));
345 catch (const SQLException& ex)
347 css::uno::Any anyEx = cppu::getCaughtException();
348 throw css::lang::WrappedTargetRuntimeException( ex.Message,
349 css::uno::Reference< css::uno::XInterface >(),
350 anyEx );
357 class CCRS_PropertySetInfo :
358 public cppu::OWeakObject,
359 public css::lang::XTypeProvider,
360 public css::beans::XPropertySetInfo
362 friend class CachedContentResultSet;
364 //my Properties
365 std::unique_ptr<Sequence< css::beans::Property >>
366 m_pProperties;
368 sal_Int32 m_nFetchSizePropertyHandle;
369 sal_Int32 m_nFetchDirectionPropertyHandle;
371 private:
372 sal_Int32
373 impl_getRemainedHandle() const;
375 bool
376 impl_queryProperty(
377 const OUString& rName
378 , css::beans::Property& rProp ) const;
379 sal_Int32
380 impl_getPos( const OUString& rName ) const;
382 static bool
383 impl_isMyPropertyName( const OUString& rName );
385 public:
386 explicit CCRS_PropertySetInfo( Reference<
387 XPropertySetInfo > const & xPropertySetInfoOrigin );
389 // XInterface
390 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
391 virtual void SAL_CALL acquire()
392 throw() override;
393 virtual void SAL_CALL release()
394 throw() override;
396 // XTypeProvider
397 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
398 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
400 // XPropertySetInfo
401 virtual Sequence< css::beans::Property > SAL_CALL
402 getProperties() override;
404 virtual css::beans::Property SAL_CALL
405 getPropertyByName( const OUString& aName ) override;
407 virtual sal_Bool SAL_CALL
408 hasPropertyByName( const OUString& Name ) override;
411 //some helping variables ( names for my special properties )
412 const char g_sPropertyNameForCount[] = "RowCount";
413 const char g_sPropertyNameForFinalCount[] = "IsRowCountFinal";
414 const char g_sPropertyNameForFetchSize[] = "FetchSize";
415 const char g_sPropertyNameForFetchDirection[] = "FetchDirection";
417 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
418 Reference< XPropertySetInfo > const & xInfo )
419 : m_nFetchSizePropertyHandle( -1 )
420 , m_nFetchDirectionPropertyHandle( -1 )
422 //initialize list of properties:
424 // it is required, that the received xInfo contains the two
425 // properties with names 'g_sPropertyNameForCount' and
426 // 'g_sPropertyNameForFinalCount'
428 if( xInfo.is() )
430 Sequence<Property> aProps = xInfo->getProperties();
431 m_pProperties.reset( new Sequence<Property> ( aProps ) );
433 else
435 OSL_FAIL( "The received XPropertySetInfo doesn't contain required properties" );
436 m_pProperties.reset( new Sequence<Property> );
439 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
440 sal_Int32 nFetchSize = impl_getPos( g_sPropertyNameForFetchSize );
441 sal_Int32 nFetchDirection = impl_getPos( g_sPropertyNameForFetchDirection );
442 sal_Int32 nDeleted = 0;
443 if( nFetchSize != -1 )
444 nDeleted++;
445 if( nFetchDirection != -1 )
446 nDeleted++;
448 std::unique_ptr<Sequence< Property > > pOrigProps(new Sequence<Property> ( *m_pProperties ));
449 sal_Int32 nOrigProps = pOrigProps->getLength();
451 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
452 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
454 if( n == nFetchSize || n == nFetchDirection )
455 m--;
456 else
457 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
460 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
461 rMyProp.Name = g_sPropertyNameForFetchSize;
462 rMyProp.Type = cppu::UnoType<sal_Int32>::get();
463 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
465 if( nFetchSize != -1 )
466 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
467 else
468 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
470 rMyProp.Handle = m_nFetchSizePropertyHandle;
474 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
475 rMyProp.Name = g_sPropertyNameForFetchDirection;
476 rMyProp.Type = cppu::UnoType<sal_Bool>::get();
477 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
479 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
483 // XInterface methods.
485 void SAL_CALL CCRS_PropertySetInfo::acquire()
486 throw()
488 OWeakObject::acquire();
491 void SAL_CALL CCRS_PropertySetInfo::release()
492 throw()
494 OWeakObject::release();
497 css::uno::Any SAL_CALL CCRS_PropertySetInfo::queryInterface( const css::uno::Type & rType )
499 css::uno::Any aRet = cppu::queryInterface( rType,
500 static_cast< XTypeProvider* >(this),
501 static_cast< XPropertySetInfo* >(this)
503 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
506 // XTypeProvider methods.
508 //list all interfaces exclusive baseclasses
509 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
510 , XTypeProvider
511 , XPropertySetInfo
514 // XPropertySetInfo methods.
516 //virtual
517 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
518 ::getProperties()
520 return *m_pProperties;
523 //virtual
524 Property SAL_CALL CCRS_PropertySetInfo
525 ::getPropertyByName( const OUString& aName )
527 Property aProp;
528 if ( impl_queryProperty( aName, aProp ) )
529 return aProp;
531 throw UnknownPropertyException(aName);
534 //virtual
535 sal_Bool SAL_CALL CCRS_PropertySetInfo
536 ::hasPropertyByName( const OUString& Name )
538 return ( impl_getPos( Name ) != -1 );
542 // impl_ methods.
545 sal_Int32 CCRS_PropertySetInfo
546 ::impl_getPos( const OUString& rName ) const
548 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
550 const Property& rMyProp = (*m_pProperties)[nN];
551 if( rMyProp.Name == rName )
552 return nN;
554 return -1;
557 bool CCRS_PropertySetInfo
558 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
560 for( const Property& rMyProp : std::as_const(*m_pProperties) )
562 if( rMyProp.Name == rName )
564 rProp.Name = rMyProp.Name;
565 rProp.Handle = rMyProp.Handle;
566 rProp.Type = rMyProp.Type;
567 rProp.Attributes = rMyProp.Attributes;
569 return true;
572 return false;
575 //static
576 bool CCRS_PropertySetInfo
577 ::impl_isMyPropertyName( const OUString& rPropertyName )
579 return ( rPropertyName == g_sPropertyNameForCount
580 || rPropertyName == g_sPropertyNameForFinalCount
581 || rPropertyName == g_sPropertyNameForFetchSize
582 || rPropertyName == g_sPropertyNameForFetchDirection );
585 sal_Int32 CCRS_PropertySetInfo
586 ::impl_getRemainedHandle( ) const
588 sal_Int32 nHandle = 1;
590 if( !m_pProperties )
592 OSL_FAIL( "Properties not initialized yet" );
593 return nHandle;
595 bool bFound = true;
596 while( bFound )
598 bFound = false;
599 for( const auto & rProp : std::as_const(*m_pProperties) )
601 if( nHandle == rProp.Handle )
603 bFound = true;
604 nHandle++;
605 break;
609 return nHandle;
615 CachedContentResultSet::CachedContentResultSet(
616 const Reference< XComponentContext > & rxContext
617 , const Reference< XResultSet > & xOrigin
618 , const Reference< XContentIdentifierMapping > &
619 xContentIdentifierMapping )
620 : ContentResultSetWrapper( xOrigin )
622 , m_xContext( rxContext )
624 , m_xContentIdentifierMapping( xContentIdentifierMapping )
625 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
626 , m_bAfterLast( false )
627 , m_nLastAppliedPos( 0 )
628 , m_bAfterLastApplied( false )
629 , m_nKnownCount( 0 )
630 , m_bFinalCount( false )
631 , m_nFetchSize(
632 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
633 , m_nFetchDirection(
634 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
636 , m_bLastReadWasFromCache( false )
637 , m_bLastCachedReadWasNull( true )
638 , m_aCache( m_xContentIdentifierMapping )
639 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
640 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
641 , m_aCacheContent( m_xContentIdentifierMapping )
642 , m_bTriedToGetTypeConverter( false )
644 m_xFetchProvider.set( m_xResultSetOrigin, UNO_QUERY );
645 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
647 m_xFetchProviderForContentAccess.set( m_xResultSetOrigin, UNO_QUERY );
648 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
650 impl_init();
653 CachedContentResultSet::~CachedContentResultSet()
655 impl_deinit();
656 //do not delete m_pMyPropSetInfo, cause it is hold via reference
660 // impl_ methods.
663 bool CachedContentResultSet
664 ::applyPositionToOrigin( sal_Int32 nRow )
666 impl_EnsureNotDisposed();
669 @returns
670 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
671 the result set.
674 osl::ResettableMutexGuard aGuard(m_aMutex);
675 OSL_ENSURE( nRow >= 0, "only positive values supported" );
676 if( !m_xResultSetOrigin.is() )
678 OSL_FAIL( "broadcaster was disposed already" );
679 return false;
681 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
683 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
684 bool bAfterLastApplied = m_bAfterLastApplied;
685 bool bAfterLast = m_bAfterLast;
686 sal_Int32 nForwardOnly = m_nForwardOnly;
688 aGuard.clear();
690 if( bAfterLastApplied || nLastAppliedPos != nRow )
692 if( nForwardOnly == 1 )
694 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
695 throw SQLException();
697 sal_Int32 nN = nRow - nLastAppliedPos;
698 sal_Int32 nM;
699 for( nM = 0; nN--; nM++ )
701 if( !m_xResultSetOrigin->next() )
702 break;
705 aGuard.reset();
706 m_nLastAppliedPos += nM;
707 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
708 return nRow == m_nLastAppliedPos;
711 if( !nRow ) //absolute( 0 ) will throw exception
713 m_xResultSetOrigin->beforeFirst();
715 aGuard.reset();
716 m_nLastAppliedPos = 0;
717 m_bAfterLastApplied = false;
718 return false;
722 //move absolute, if !nLastAppliedPos
723 //because move relative would throw exception
724 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
726 bool bValid = m_xResultSetOrigin->absolute( nRow );
728 aGuard.reset();
729 m_nLastAppliedPos = nRow;
730 m_bAfterLastApplied = !bValid;
731 return bValid;
733 else
735 bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
737 aGuard.reset();
738 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
739 m_bAfterLastApplied = !bValid;
740 return bValid;
743 catch (const SQLException&)
745 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
747 sal_Int32 nN = nRow - nLastAppliedPos;
748 sal_Int32 nM;
749 for( nM = 0; nN--; nM++ )
751 if( !m_xResultSetOrigin->next() )
752 break;
755 aGuard.reset();
756 m_nLastAppliedPos += nM;
757 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
759 else
760 throw;
763 return nRow == m_nLastAppliedPos;
765 return true;
769 //define for fetching data
772 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
773 bool bDirection = !!( \
774 nFetchDirection != FetchDirection::REVERSE ); \
775 FetchResult aResult = \
776 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
777 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
778 aCache.loadData( aResult ); \
779 sal_Int32 nMax = aCache.getMaxRow(); \
780 sal_Int32 nCurCount = m_nKnownCount; \
781 bool bIsFinalCount = aCache.hasKnownLast(); \
782 bool bCurIsFinalCount = m_bFinalCount; \
783 aGuard2.clear(); \
784 if( nMax > nCurCount ) \
785 impl_changeRowCount( nCurCount, nMax ); \
786 if( bIsFinalCount && !bCurIsFinalCount ) \
787 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
789 void CachedContentResultSet
790 ::impl_fetchData( sal_Int32 nRow
791 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
793 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
796 void CachedContentResultSet
797 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
799 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
800 if( nNew <= nOld )
801 return;
803 //create PropertyChangeEvent and set value
804 PropertyChangeEvent aEvt;
806 osl::Guard< osl::Mutex > aGuard( m_aMutex );
807 aEvt.Source = static_cast< XPropertySet * >( this );
808 aEvt.Further = false;
809 aEvt.OldValue <<= nOld;
810 aEvt.NewValue <<= nNew;
812 m_nKnownCount = nNew;
815 //send PropertyChangeEvent to listeners
816 impl_notifyPropertyChangeListeners( aEvt );
819 void CachedContentResultSet
820 ::impl_changeIsRowCountFinal( bool bOld, bool bNew )
822 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
823 if( bOld || !bNew )
824 return;
826 //create PropertyChangeEvent and set value
827 PropertyChangeEvent aEvt;
829 osl::Guard< osl::Mutex > aGuard( m_aMutex );
830 aEvt.Source = static_cast< XPropertySet * >( this );
831 aEvt.Further = false;
832 aEvt.OldValue <<= bOld;
833 aEvt.NewValue <<= bNew;
835 m_bFinalCount = bNew;
838 //send PropertyChangeEvent to listeners
839 impl_notifyPropertyChangeListeners( aEvt );
842 bool CachedContentResultSet
843 ::impl_isKnownValidPosition( sal_Int32 nRow )
845 return m_nKnownCount && nRow
846 && nRow <= m_nKnownCount;
849 bool CachedContentResultSet
850 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
852 if( !nRow )
853 return true;
854 if( !m_bFinalCount )
855 return false;
856 return nRow > m_nKnownCount;
860 //virtual
861 void CachedContentResultSet
862 ::impl_initPropertySetInfo()
864 ContentResultSetWrapper::impl_initPropertySetInfo();
866 osl::Guard< osl::Mutex > aGuard( m_aMutex );
867 if( m_xMyPropertySetInfo.is() )
868 return;
869 m_xMyPropertySetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
870 m_xPropertySetInfo = m_xMyPropertySetInfo.get();
874 // XInterface methods.
875 void SAL_CALL CachedContentResultSet::acquire()
876 throw()
878 OWeakObject::acquire();
881 void SAL_CALL CachedContentResultSet::release()
882 throw()
884 OWeakObject::release();
887 Any SAL_CALL CachedContentResultSet
888 ::queryInterface( const Type& rType )
890 //list all interfaces inclusive baseclasses of interfaces
892 Any aRet = ContentResultSetWrapper::queryInterface( rType );
893 if( aRet.hasValue() )
894 return aRet;
896 aRet = cppu::queryInterface( rType,
897 static_cast< XTypeProvider* >( this ),
898 static_cast< XServiceInfo* >( this ) );
900 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
904 // XTypeProvider methods.
906 //list all interfaces exclusive baseclasses
907 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
908 , XTypeProvider
909 , XServiceInfo
910 , XComponent
911 , XCloseable
912 , XResultSetMetaDataSupplier
913 , XPropertySet
915 , XPropertyChangeListener
916 , XVetoableChangeListener
918 , XContentAccess
920 , XResultSet
921 , XRow );
924 // XServiceInfo methods.
926 OUString SAL_CALL CachedContentResultSet::getImplementationName()
928 return "com.sun.star.comp.ucb.CachedContentResultSet";
931 sal_Bool SAL_CALL CachedContentResultSet::supportsService( const OUString& ServiceName )
933 return cppu::supportsService( this, ServiceName );
936 css::uno::Sequence< OUString > SAL_CALL CachedContentResultSet::getSupportedServiceNames()
938 return { "com.sun.star.ucb.CachedContentResultSet" };
943 // XPropertySet methods. ( inherited )
946 // virtual
947 void SAL_CALL CachedContentResultSet
948 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
950 impl_EnsureNotDisposed();
952 if( !getPropertySetInfo().is() )
954 OSL_FAIL( "broadcaster was disposed already" );
955 throw UnknownPropertyException();
958 Property aProp = m_xMyPropertySetInfo->getPropertyByName( aPropertyName );
959 //throws UnknownPropertyException, if so
961 if( aProp.Attributes & PropertyAttribute::READONLY )
963 //It is assumed, that the properties
964 //'RowCount' and 'IsRowCountFinal' are readonly!
965 throw IllegalArgumentException();
967 if( aProp.Name == g_sPropertyNameForFetchDirection )
969 //check value
970 sal_Int32 nNew;
971 if( !( aValue >>= nNew ) )
973 throw IllegalArgumentException();
976 if( nNew == FetchDirection::UNKNOWN )
978 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
980 else if( nNew != FetchDirection::FORWARD && nNew != FetchDirection::REVERSE )
982 throw IllegalArgumentException();
985 //create PropertyChangeEvent and set value
986 PropertyChangeEvent aEvt;
988 osl::Guard< osl::Mutex > aGuard( m_aMutex );
989 aEvt.Source = static_cast< XPropertySet * >( this );
990 aEvt.PropertyName = aPropertyName;
991 aEvt.Further = false;
992 aEvt.PropertyHandle = m_xMyPropertySetInfo->
993 m_nFetchDirectionPropertyHandle;
994 aEvt.OldValue <<= m_nFetchDirection;
995 aEvt.NewValue <<= nNew;
997 m_nFetchDirection = nNew;
1000 //send PropertyChangeEvent to listeners
1001 impl_notifyPropertyChangeListeners( aEvt );
1003 else if( aProp.Name == g_sPropertyNameForFetchSize )
1005 //check value
1006 sal_Int32 nNew;
1007 if( !( aValue >>= nNew ) )
1009 throw IllegalArgumentException();
1012 if( nNew < 0 )
1014 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1017 //create PropertyChangeEvent and set value
1018 PropertyChangeEvent aEvt;
1020 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1021 aEvt.Source = static_cast< XPropertySet * >( this );
1022 aEvt.PropertyName = aPropertyName;
1023 aEvt.Further = false;
1024 aEvt.PropertyHandle = m_xMyPropertySetInfo->
1025 m_nFetchSizePropertyHandle;
1026 aEvt.OldValue <<= m_nFetchSize;
1027 aEvt.NewValue <<= nNew;
1029 m_nFetchSize = nNew;
1032 //send PropertyChangeEvent to listeners
1033 impl_notifyPropertyChangeListeners( aEvt );
1035 else
1037 impl_init_xPropertySetOrigin();
1039 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1040 if( !m_xPropertySetOrigin.is() )
1042 OSL_FAIL( "broadcaster was disposed already" );
1043 return;
1046 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1051 // virtual
1052 Any SAL_CALL CachedContentResultSet
1053 ::getPropertyValue( const OUString& rPropertyName )
1055 impl_EnsureNotDisposed();
1057 if( !getPropertySetInfo().is() )
1059 OSL_FAIL( "broadcaster was disposed already" );
1060 throw UnknownPropertyException();
1063 m_xMyPropertySetInfo->getPropertyByName( rPropertyName );
1064 //throws UnknownPropertyException, if so
1066 Any aValue;
1067 if( rPropertyName == g_sPropertyNameForCount )
1069 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1070 aValue <<= m_nKnownCount;
1072 else if( rPropertyName == g_sPropertyNameForFinalCount )
1074 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1075 aValue <<= m_bFinalCount;
1077 else if( rPropertyName == g_sPropertyNameForFetchSize )
1079 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1080 aValue <<= m_nFetchSize;
1082 else if( rPropertyName == g_sPropertyNameForFetchDirection )
1084 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1085 aValue <<= m_nFetchDirection;
1087 else
1089 impl_init_xPropertySetOrigin();
1091 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1092 if( !m_xPropertySetOrigin.is() )
1094 OSL_FAIL( "broadcaster was disposed already" );
1095 throw UnknownPropertyException();
1098 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1100 return aValue;
1104 // own methods. ( inherited )
1107 //virtual
1108 void CachedContentResultSet
1109 ::impl_disposing( const EventObject& rEventObject )
1112 impl_EnsureNotDisposed();
1113 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1114 //release all references to the broadcaster:
1115 m_xFetchProvider.clear();
1116 m_xFetchProviderForContentAccess.clear();
1118 ContentResultSetWrapper::impl_disposing( rEventObject );
1121 //virtual
1122 void CachedContentResultSet
1123 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1125 impl_EnsureNotDisposed();
1127 PropertyChangeEvent aEvt( rEvt );
1128 aEvt.Source = static_cast< XPropertySet * >( this );
1129 aEvt.Further = false;
1132 if( CCRS_PropertySetInfo
1133 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1135 //don't notify foreign events on fetchsize and fetchdirection
1136 if( aEvt.PropertyName == g_sPropertyNameForFetchSize
1137 || aEvt.PropertyName == g_sPropertyNameForFetchDirection )
1138 return;
1140 //adjust my props 'RowCount' and 'IsRowCountFinal'
1141 if( aEvt.PropertyName == g_sPropertyNameForCount )
1142 {//RowCount changed
1144 //check value
1145 sal_Int32 nNew = 0;
1146 if( !( aEvt.NewValue >>= nNew ) )
1148 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1149 return;
1152 impl_changeRowCount( m_nKnownCount, nNew );
1154 else if( aEvt.PropertyName == g_sPropertyNameForFinalCount )
1155 {//IsRowCountFinal changed
1157 //check value
1158 bool bNew = false;
1159 if( !( aEvt.NewValue >>= bNew ) )
1161 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1162 return;
1164 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1166 return;
1170 impl_notifyPropertyChangeListeners( aEvt );
1174 //virtual
1175 void CachedContentResultSet
1176 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1178 impl_EnsureNotDisposed();
1180 //don't notify events on my properties, cause they are not vetoable
1181 if( CCRS_PropertySetInfo
1182 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1184 return;
1188 PropertyChangeEvent aEvt( rEvt );
1189 aEvt.Source = static_cast< XPropertySet * >( this );
1190 aEvt.Further = false;
1192 impl_notifyVetoableChangeListeners( aEvt );
1196 // XContentAccess methods. ( inherited ) ( -- position dependent )
1199 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1200 impl_EnsureNotDisposed(); \
1201 osl::ResettableMutexGuard aGuard(m_aMutex); \
1202 sal_Int32 nRow = m_nRow; \
1203 sal_Int32 nFetchSize = m_nFetchSize; \
1204 sal_Int32 nFetchDirection = m_nFetchDirection; \
1205 if( !m_aCache##XXX.hasRow( nRow ) ) \
1207 try \
1209 bool isCleared = false; \
1210 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1212 if( !m_xFetchProviderForContentAccess.is() ) \
1214 OSL_FAIL( "broadcaster was disposed already" ); \
1215 throw RuntimeException(); \
1217 aGuard.clear(); \
1218 isCleared = true; \
1219 if( impl_isForwardOnly() ) \
1220 applyPositionToOrigin( nRow ); \
1222 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1224 if (isCleared) \
1226 aGuard.reset(); \
1228 if( !m_aCache##XXX.hasRow( nRow ) ) \
1230 aGuard.clear(); \
1231 applyPositionToOrigin( nRow ); \
1232 TYPE aRet = ContentResultSetWrapper::queryXXX();\
1233 if( m_xContentIdentifierMapping.is() ) \
1234 return m_xContentIdentifierMapping->map##XXX( aRet );\
1235 return aRet; \
1238 catch (const RuntimeException&) \
1240 throw; \
1242 catch (const Exception& e) \
1244 Any a(cppu::getCaughtException()); \
1245 throw WrappedTargetRuntimeException( \
1246 "wrapped Exception " + e.Message, \
1247 Reference<XInterface>(), a); \
1250 return m_aCache##XXX.get##XXX( nRow );
1252 // virtual
1253 OUString SAL_CALL CachedContentResultSet
1254 ::queryContentIdentifierString()
1256 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1260 // virtual
1261 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1262 ::queryContentIdentifier()
1264 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1268 // virtual
1269 Reference< XContent > SAL_CALL CachedContentResultSet
1270 ::queryContent()
1272 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1276 // XResultSet methods. ( inherited )
1278 //virtual
1280 sal_Bool SAL_CALL CachedContentResultSet
1281 ::next()
1283 impl_EnsureNotDisposed();
1285 osl::ResettableMutexGuard aGuard(m_aMutex);
1286 //after last
1287 if( m_bAfterLast )
1288 return false;
1289 //last
1290 aGuard.clear();
1291 if( isLast() )
1293 aGuard.reset();
1294 m_nRow++;
1295 m_bAfterLast = true;
1296 return false;
1298 aGuard.reset();
1299 //known valid position
1300 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1302 m_nRow++;
1303 return true;
1306 //unknown position
1307 sal_Int32 nRow = m_nRow;
1308 aGuard.clear();
1310 bool bValid = applyPositionToOrigin( nRow + 1 );
1312 aGuard.reset();
1313 m_nRow = nRow + 1;
1314 m_bAfterLast = !bValid;
1315 return bValid;
1318 //virtual
1319 sal_Bool SAL_CALL CachedContentResultSet
1320 ::previous()
1322 impl_EnsureNotDisposed();
1324 if( impl_isForwardOnly() )
1325 throw SQLException();
1327 osl::ResettableMutexGuard aGuard(m_aMutex);
1328 //before first ?:
1329 if( !m_bAfterLast && !m_nRow )
1330 return false;
1331 //first ?:
1332 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1334 m_nRow--;
1335 m_bAfterLast = false;
1336 return false;
1338 //known valid position ?:
1339 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1341 m_nRow--;
1342 m_bAfterLast = false;
1343 return true;
1345 //unknown position:
1346 sal_Int32 nRow = m_nRow;
1347 aGuard.clear();
1349 bool bValid = applyPositionToOrigin( nRow - 1 );
1351 aGuard.reset();
1352 m_nRow = nRow - 1;
1353 m_bAfterLast = false;
1354 return bValid;
1357 //virtual
1358 sal_Bool SAL_CALL CachedContentResultSet
1359 ::absolute( sal_Int32 row )
1361 impl_EnsureNotDisposed();
1363 if( !row )
1364 throw SQLException();
1366 if( impl_isForwardOnly() )
1367 throw SQLException();
1369 osl::ResettableMutexGuard aGuard(m_aMutex);
1371 if( !m_xResultSetOrigin.is() )
1373 OSL_FAIL( "broadcaster was disposed already" );
1374 return false;
1376 if( row < 0 )
1378 if( m_bFinalCount )
1380 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1381 bool bValid = true;
1382 if( nNewRow <= 0 )
1384 nNewRow = 0;
1385 bValid = false;
1387 m_nRow = nNewRow;
1388 m_bAfterLast = false;
1389 return bValid;
1391 //unknown final count:
1392 aGuard.clear();
1394 bool bValid = m_xResultSetOrigin->absolute( row );
1396 aGuard.reset();
1397 if( m_bFinalCount )
1399 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1400 if( nNewRow < 0 )
1401 nNewRow = 0;
1402 m_nLastAppliedPos = nNewRow;
1403 m_nRow = nNewRow;
1404 m_bAfterLastApplied = m_bAfterLast = false;
1405 return bValid;
1407 aGuard.clear();
1409 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1411 aGuard.reset();
1412 m_nLastAppliedPos = nCurRow;
1413 m_nRow = nCurRow;
1414 m_bAfterLast = false;
1415 return nCurRow != 0;
1417 //row > 0:
1418 if( m_bFinalCount )
1420 if( row > m_nKnownCount )
1422 m_nRow = m_nKnownCount + 1;
1423 m_bAfterLast = true;
1424 return false;
1426 m_nRow = row;
1427 m_bAfterLast = false;
1428 return true;
1430 //unknown new position:
1431 aGuard.clear();
1433 bool bValid = m_xResultSetOrigin->absolute( row );
1435 aGuard.reset();
1436 if( m_bFinalCount )
1438 sal_Int32 nNewRow = row;
1439 if( nNewRow > m_nKnownCount )
1441 nNewRow = m_nKnownCount + 1;
1442 m_bAfterLastApplied = m_bAfterLast = true;
1444 else
1445 m_bAfterLastApplied = m_bAfterLast = false;
1447 m_nLastAppliedPos = nNewRow;
1448 m_nRow = nNewRow;
1449 return bValid;
1451 aGuard.clear();
1453 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1454 bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1456 aGuard.reset();
1457 m_nLastAppliedPos = nCurRow;
1458 m_nRow = nCurRow;
1459 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1460 return nCurRow && !bIsAfterLast;
1463 //virtual
1464 sal_Bool SAL_CALL CachedContentResultSet
1465 ::relative( sal_Int32 rows )
1467 impl_EnsureNotDisposed();
1469 if( impl_isForwardOnly() )
1470 throw SQLException();
1472 osl::ResettableMutexGuard aGuard(m_aMutex);
1473 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1474 throw SQLException();
1476 if( !rows )
1477 return true;
1479 sal_Int32 nNewRow = m_nRow + rows;
1480 if( nNewRow < 0 )
1481 nNewRow = 0;
1483 if( impl_isKnownValidPosition( nNewRow ) )
1485 m_nRow = nNewRow;
1486 m_bAfterLast = false;
1487 return true;
1489 else
1491 //known invalid new position:
1492 if( nNewRow == 0 )
1494 m_bAfterLast = false;
1495 m_nRow = 0;
1496 return false;
1498 if( m_bFinalCount && nNewRow > m_nKnownCount )
1500 m_bAfterLast = true;
1501 m_nRow = m_nKnownCount + 1;
1502 return false;
1504 //unknown new position:
1505 aGuard.clear();
1506 bool bValid = applyPositionToOrigin( nNewRow );
1508 aGuard.reset();
1509 m_nRow = nNewRow;
1510 m_bAfterLast = !bValid; // only nNewRow > 0 possible here
1511 return bValid;
1516 //virtual
1517 sal_Bool SAL_CALL CachedContentResultSet
1518 ::first()
1520 impl_EnsureNotDisposed();
1522 if( impl_isForwardOnly() )
1523 throw SQLException();
1525 osl::ResettableMutexGuard aGuard(m_aMutex);
1526 if( impl_isKnownValidPosition( 1 ) )
1528 m_nRow = 1;
1529 m_bAfterLast = false;
1530 return true;
1532 if( impl_isKnownInvalidPosition( 1 ) )
1534 m_nRow = 1;
1535 m_bAfterLast = false;
1536 return false;
1538 //unknown position
1539 aGuard.clear();
1541 bool bValid = applyPositionToOrigin( 1 );
1543 aGuard.reset();
1544 m_nRow = 1;
1545 m_bAfterLast = false;
1546 return bValid;
1549 //virtual
1550 sal_Bool SAL_CALL CachedContentResultSet
1551 ::last()
1553 impl_EnsureNotDisposed();
1555 if( impl_isForwardOnly() )
1556 throw SQLException();
1558 osl::ResettableMutexGuard aGuard(m_aMutex);
1559 if( m_bFinalCount )
1561 m_nRow = m_nKnownCount;
1562 m_bAfterLast = false;
1563 return m_nKnownCount != 0;
1565 //unknown position
1566 if( !m_xResultSetOrigin.is() )
1568 OSL_FAIL( "broadcaster was disposed already" );
1569 return false;
1571 aGuard.clear();
1573 bool bValid = m_xResultSetOrigin->last();
1575 aGuard.reset();
1576 m_bAfterLastApplied = m_bAfterLast = false;
1577 if( m_bFinalCount )
1579 m_nLastAppliedPos = m_nKnownCount;
1580 m_nRow = m_nKnownCount;
1581 return bValid;
1583 aGuard.clear();
1585 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1587 aGuard.reset();
1588 m_nLastAppliedPos = nCurRow;
1589 m_nRow = nCurRow;
1590 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1591 m_nKnownCount = nCurRow;
1592 m_bFinalCount = true;
1593 return nCurRow != 0;
1596 //virtual
1597 void SAL_CALL CachedContentResultSet
1598 ::beforeFirst()
1600 impl_EnsureNotDisposed();
1602 if( impl_isForwardOnly() )
1603 throw SQLException();
1605 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1606 m_nRow = 0;
1607 m_bAfterLast = false;
1610 //virtual
1611 void SAL_CALL CachedContentResultSet
1612 ::afterLast()
1614 impl_EnsureNotDisposed();
1616 if( impl_isForwardOnly() )
1617 throw SQLException();
1619 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1620 m_nRow = 1;
1621 m_bAfterLast = true;
1624 //virtual
1625 sal_Bool SAL_CALL CachedContentResultSet
1626 ::isAfterLast()
1628 impl_EnsureNotDisposed();
1630 osl::ResettableMutexGuard aGuard(m_aMutex);
1631 if( !m_bAfterLast )
1632 return false;
1633 if( m_nKnownCount )
1634 return m_bAfterLast;
1635 if( m_bFinalCount )
1636 return false;
1638 if( !m_xResultSetOrigin.is() )
1640 OSL_FAIL( "broadcaster was disposed already" );
1641 return false;
1643 aGuard.clear();
1645 //find out whether the original resultset contains rows or not
1646 m_xResultSetOrigin->afterLast();
1648 aGuard.reset();
1649 m_bAfterLastApplied = true;
1650 aGuard.clear();
1652 return m_xResultSetOrigin->isAfterLast();
1655 //virtual
1656 sal_Bool SAL_CALL CachedContentResultSet
1657 ::isBeforeFirst()
1659 impl_EnsureNotDisposed();
1661 osl::ResettableMutexGuard aGuard(m_aMutex);
1662 if( m_bAfterLast )
1663 return false;
1664 if( m_nRow )
1665 return false;
1666 if( m_nKnownCount )
1667 return true;
1668 if( m_bFinalCount )
1669 return false;
1671 if( !m_xResultSetOrigin.is() )
1673 OSL_FAIL( "broadcaster was disposed already" );
1674 return false;
1676 aGuard.clear();
1678 //find out whether the original resultset contains rows or not
1679 m_xResultSetOrigin->beforeFirst();
1681 aGuard.reset();
1682 m_bAfterLastApplied = false;
1683 m_nLastAppliedPos = 0;
1684 aGuard.clear();
1686 return m_xResultSetOrigin->isBeforeFirst();
1689 //virtual
1690 sal_Bool SAL_CALL CachedContentResultSet
1691 ::isFirst()
1693 impl_EnsureNotDisposed();
1695 sal_Int32 nRow = 0;
1696 Reference< XResultSet > xResultSetOrigin;
1699 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1700 if( m_bAfterLast )
1701 return false;
1702 if( m_nRow != 1 )
1703 return false;
1704 if( m_nKnownCount )
1705 return true;
1706 if( m_bFinalCount )
1707 return false;
1709 nRow = m_nRow;
1710 xResultSetOrigin = m_xResultSetOrigin;
1713 //need to ask origin
1715 if( applyPositionToOrigin( nRow ) )
1716 return xResultSetOrigin->isFirst();
1717 else
1718 return false;
1722 //virtual
1723 sal_Bool SAL_CALL CachedContentResultSet
1724 ::isLast()
1726 impl_EnsureNotDisposed();
1728 sal_Int32 nRow = 0;
1729 Reference< XResultSet > xResultSetOrigin;
1731 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1732 if( m_bAfterLast )
1733 return false;
1734 if( m_nRow < m_nKnownCount )
1735 return false;
1736 if( m_bFinalCount )
1737 return m_nKnownCount && m_nRow == m_nKnownCount;
1739 nRow = m_nRow;
1740 xResultSetOrigin = m_xResultSetOrigin;
1743 //need to ask origin
1745 if( applyPositionToOrigin( nRow ) )
1746 return xResultSetOrigin->isLast();
1747 else
1748 return false;
1753 //virtual
1754 sal_Int32 SAL_CALL CachedContentResultSet
1755 ::getRow()
1757 impl_EnsureNotDisposed();
1759 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1760 if( m_bAfterLast )
1761 return 0;
1762 return m_nRow;
1765 //virtual
1766 void SAL_CALL CachedContentResultSet
1767 ::refreshRow()
1769 impl_EnsureNotDisposed();
1771 //the ContentResultSet is static and will not change
1772 //therefore we don't need to reload anything
1775 //virtual
1776 sal_Bool SAL_CALL CachedContentResultSet
1777 ::rowUpdated()
1779 impl_EnsureNotDisposed();
1781 //the ContentResultSet is static and will not change
1782 return false;
1784 //virtual
1785 sal_Bool SAL_CALL CachedContentResultSet
1786 ::rowInserted()
1788 impl_EnsureNotDisposed();
1790 //the ContentResultSet is static and will not change
1791 return false;
1794 //virtual
1795 sal_Bool SAL_CALL CachedContentResultSet
1796 ::rowDeleted()
1798 impl_EnsureNotDisposed();
1800 //the ContentResultSet is static and will not change
1801 return false;
1804 //virtual
1805 Reference< XInterface > SAL_CALL CachedContentResultSet
1806 ::getStatement()
1808 impl_EnsureNotDisposed();
1809 //@todo ?return anything
1810 return Reference< XInterface >();
1814 // XRow methods. ( inherited )
1817 //virtual
1818 sal_Bool SAL_CALL CachedContentResultSet
1819 ::wasNull()
1821 impl_EnsureNotDisposed();
1822 impl_init_xRowOrigin();
1824 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1825 if( m_bLastReadWasFromCache )
1826 return m_bLastCachedReadWasNull;
1827 if( !m_xRowOrigin.is() )
1829 OSL_FAIL( "broadcaster was disposed already" );
1830 return false;
1833 return m_xRowOrigin->wasNull();
1836 //virtual
1837 OUString SAL_CALL CachedContentResultSet
1838 ::getString( sal_Int32 columnIndex )
1840 return rowOriginGet<OUString>(&css::sdbc::XRow::getString, columnIndex);
1843 //virtual
1844 sal_Bool SAL_CALL CachedContentResultSet
1845 ::getBoolean( sal_Int32 columnIndex )
1847 return rowOriginGet<sal_Bool>(&css::sdbc::XRow::getBoolean, columnIndex);
1850 //virtual
1851 sal_Int8 SAL_CALL CachedContentResultSet
1852 ::getByte( sal_Int32 columnIndex )
1854 return rowOriginGet<sal_Int8>(&css::sdbc::XRow::getByte, columnIndex);
1857 //virtual
1858 sal_Int16 SAL_CALL CachedContentResultSet
1859 ::getShort( sal_Int32 columnIndex )
1861 return rowOriginGet<sal_Int16>(&css::sdbc::XRow::getShort, columnIndex);
1864 //virtual
1865 sal_Int32 SAL_CALL CachedContentResultSet
1866 ::getInt( sal_Int32 columnIndex )
1868 return rowOriginGet<sal_Int32>(&css::sdbc::XRow::getInt, columnIndex);
1871 //virtual
1872 sal_Int64 SAL_CALL CachedContentResultSet
1873 ::getLong( sal_Int32 columnIndex )
1875 return rowOriginGet<sal_Int64>(&css::sdbc::XRow::getLong, columnIndex);
1878 //virtual
1879 float SAL_CALL CachedContentResultSet
1880 ::getFloat( sal_Int32 columnIndex )
1882 return rowOriginGet<float>(&css::sdbc::XRow::getFloat, columnIndex);
1885 //virtual
1886 double SAL_CALL CachedContentResultSet
1887 ::getDouble( sal_Int32 columnIndex )
1889 return rowOriginGet<double>(&css::sdbc::XRow::getDouble, columnIndex);
1892 //virtual
1893 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
1894 ::getBytes( sal_Int32 columnIndex )
1896 return rowOriginGet< css::uno::Sequence<sal_Int8> >(
1897 &css::sdbc::XRow::getBytes, columnIndex);
1900 //virtual
1901 Date SAL_CALL CachedContentResultSet
1902 ::getDate( sal_Int32 columnIndex )
1904 return rowOriginGet<css::util::Date>(
1905 &css::sdbc::XRow::getDate, columnIndex);
1908 //virtual
1909 Time SAL_CALL CachedContentResultSet
1910 ::getTime( sal_Int32 columnIndex )
1912 return rowOriginGet<css::util::Time>(
1913 &css::sdbc::XRow::getTime, columnIndex);
1916 //virtual
1917 DateTime SAL_CALL CachedContentResultSet
1918 ::getTimestamp( sal_Int32 columnIndex )
1920 return rowOriginGet<css::util::DateTime>(
1921 &css::sdbc::XRow::getTimestamp, columnIndex);
1924 //virtual
1925 Reference< css::io::XInputStream >
1926 SAL_CALL CachedContentResultSet
1927 ::getBinaryStream( sal_Int32 columnIndex )
1929 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
1930 &css::sdbc::XRow::getBinaryStream, columnIndex);
1933 //virtual
1934 Reference< css::io::XInputStream >
1935 SAL_CALL CachedContentResultSet
1936 ::getCharacterStream( sal_Int32 columnIndex )
1938 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
1939 &css::sdbc::XRow::getCharacterStream, columnIndex);
1942 //virtual
1943 Any SAL_CALL CachedContentResultSet
1944 ::getObject( sal_Int32 columnIndex,
1945 const Reference<
1946 css::container::XNameAccess >& typeMap )
1948 //if you change this function please pay attention to
1949 //function template rowOriginGet, where this is similar implemented
1951 osl::ResettableMutexGuard aGuard(m_aMutex);
1952 sal_Int32 nRow = m_nRow;
1953 sal_Int32 nFetchSize = m_nFetchSize;
1954 sal_Int32 nFetchDirection = m_nFetchDirection;
1955 if( !m_aCache.hasRow( nRow ) )
1957 bool isCleared = false;
1958 if( !m_aCache.hasCausedException( nRow ) )
1960 if( !m_xFetchProvider.is() )
1962 OSL_FAIL( "broadcaster was disposed already" );
1963 return Any();
1965 isCleared = true;
1966 aGuard.clear();
1968 impl_fetchData( nRow, nFetchSize, nFetchDirection );
1970 if (isCleared)
1972 aGuard.reset();
1974 if( !m_aCache.hasRow( nRow ) )
1976 m_bLastReadWasFromCache = false;
1977 aGuard.clear();
1978 applyPositionToOrigin( nRow );
1979 impl_init_xRowOrigin();
1980 return m_xRowOrigin->getObject( columnIndex, typeMap );
1983 //@todo: pay attention to typeMap
1984 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
1985 m_bLastReadWasFromCache = true;
1986 m_bLastCachedReadWasNull = !rValue.hasValue();
1987 return rValue;
1990 //virtual
1991 Reference< XRef > SAL_CALL CachedContentResultSet
1992 ::getRef( sal_Int32 columnIndex )
1994 return rowOriginGet< css::uno::Reference<css::sdbc::XRef> >(
1995 &css::sdbc::XRow::getRef, columnIndex);
1998 //virtual
1999 Reference< XBlob > SAL_CALL CachedContentResultSet
2000 ::getBlob( sal_Int32 columnIndex )
2002 return rowOriginGet< css::uno::Reference<css::sdbc::XBlob> >(
2003 &css::sdbc::XRow::getBlob, columnIndex);
2006 //virtual
2007 Reference< XClob > SAL_CALL CachedContentResultSet
2008 ::getClob( sal_Int32 columnIndex )
2010 return rowOriginGet< css::uno::Reference<css::sdbc::XClob> >(
2011 &css::sdbc::XRow::getClob, columnIndex);
2014 //virtual
2015 Reference< XArray > SAL_CALL CachedContentResultSet
2016 ::getArray( sal_Int32 columnIndex )
2018 return rowOriginGet< css::uno::Reference<css::sdbc::XArray> >(
2019 &css::sdbc::XRow::getArray, columnIndex);
2023 // Type Converter Support
2026 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2028 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2030 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2032 m_bTriedToGetTypeConverter = true;
2033 m_xTypeConverter.set( Converter::create(m_xContext) );
2035 OSL_ENSURE( m_xTypeConverter.is(),
2036 "PropertyValueSet::getTypeConverter() - "
2037 "Service 'com.sun.star.script.Converter' n/a!" );
2039 return m_xTypeConverter;
2045 CachedContentResultSetFactory::CachedContentResultSetFactory(
2046 const Reference< XComponentContext > & rxContext )
2048 m_xContext = rxContext;
2051 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2055 // CachedContentResultSetFactory XServiceInfo methods.
2057 OUString SAL_CALL CachedContentResultSetFactory::getImplementationName()
2059 return "com.sun.star.comp.ucb.CachedContentResultSetFactory";
2061 sal_Bool SAL_CALL CachedContentResultSetFactory::supportsService( const OUString& ServiceName )
2063 return cppu::supportsService( this, ServiceName );
2065 css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetFactory::getSupportedServiceNames()
2067 return { "com.sun.star.ucb.CachedContentResultSetFactory" };
2070 // Service factory implementation.
2074 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
2075 ucb_CachedContentResultSetFactory_get_implementation(
2076 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
2078 return cppu::acquire(new CachedContentResultSetFactory(context));
2082 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2085 //virtual
2086 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2087 ::createCachedContentResultSet(
2088 const Reference< XResultSet > & xSource,
2089 const Reference< XContentIdentifierMapping > & xMapping )
2091 Reference< XResultSet > xRet = new CachedContentResultSet( m_xContext, xSource, xMapping );
2092 return xRet;
2095 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */