fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blobdfa021af6e7683d7ed5bf651038bf953454a8377
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cachedcontentresultset.hxx>
22 #include <com/sun/star/sdbc/FetchDirection.hpp>
23 #include <com/sun/star/ucb/FetchError.hpp>
24 #include <com/sun/star/ucb/ResultSetException.hpp>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/script/Converter.hpp>
27 #include <com/sun/star/sdbc/ResultSetType.hpp>
28 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
29 #include <rtl/ustring.hxx>
30 #include <osl/diagnose.h>
31 #include <comphelper/processfactory.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <boost/scoped_ptr.hpp>
35 using namespace com::sun::star::beans;
36 using namespace com::sun::star::lang;
37 using namespace com::sun::star::script;
38 using namespace com::sun::star::sdbc;
39 using namespace com::sun::star::ucb;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::util;
42 using namespace cppu;
45 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
46 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
48 //if you change this function template please pay attention to
49 //function getObject, where this is similar implemented
51 template<typename T> T CachedContentResultSet::rowOriginGet(
52 T (SAL_CALL css::sdbc::XRow::* f)(sal_Int32), sal_Int32 columnIndex)
54 impl_EnsureNotDisposed();
55 ReacquireableGuard aGuard( m_aMutex );
56 sal_Int32 nRow = m_nRow;
57 sal_Int32 nFetchSize = m_nFetchSize;
58 sal_Int32 nFetchDirection = m_nFetchDirection;
59 if( !m_aCache.hasRow( nRow ) )
61 if( !m_aCache.hasCausedException( nRow ) )
63 if( !m_xFetchProvider.is() )
65 OSL_FAIL( "broadcaster was disposed already" );
66 throw SQLException();
68 aGuard.clear();
69 if( impl_isForwardOnly() )
70 applyPositionToOrigin( nRow );
72 impl_fetchData( nRow, nFetchSize, nFetchDirection );
74 aGuard.reacquire();
75 if( !m_aCache.hasRow( nRow ) )
77 m_bLastReadWasFromCache = false;
78 aGuard.clear();
79 applyPositionToOrigin( nRow );
80 impl_init_xRowOrigin();
81 return (m_xRowOrigin.get()->*f)( columnIndex );
84 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
85 T aRet = T();
86 m_bLastReadWasFromCache = true;
87 m_bLastCachedReadWasNull = !( rValue >>= aRet );
88 /* Last chance. Try type converter service... */
89 if ( m_bLastCachedReadWasNull && rValue.hasValue() )
91 Reference< XTypeConverter > xConverter = getTypeConverter();
92 if ( xConverter.is() )
94 try
96 Any aConvAny = xConverter->convertTo(
97 rValue,
98 cppu::UnoType<T>::get() );
99 m_bLastCachedReadWasNull = !( aConvAny >>= aRet );
101 catch (const IllegalArgumentException&)
104 catch (const CannotConvertException&)
109 return aRet;
114 // CCRS_Cache methoeds.
118 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
119 const Reference< XContentIdentifierMapping > & xMapping )
120 : m_pResult( NULL )
121 , m_xContentIdentifierMapping( xMapping )
122 , m_pMappedReminder( NULL )
126 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
128 delete m_pResult;
131 void SAL_CALL CachedContentResultSet::CCRS_Cache
132 ::clear()
134 if( m_pResult )
136 delete m_pResult;
137 m_pResult = NULL;
139 clearMappedReminder();
142 void SAL_CALL CachedContentResultSet::CCRS_Cache
143 ::loadData( const FetchResult& rResult )
145 clear();
146 m_pResult = new FetchResult( rResult );
149 bool SAL_CALL CachedContentResultSet::CCRS_Cache
150 ::hasRow( sal_Int32 row )
152 if( !m_pResult )
153 return false;
154 long nStart = m_pResult->StartIndex;
155 long nEnd = nStart;
156 if( m_pResult->Orientation )
157 nEnd += m_pResult->Rows.getLength() - 1;
158 else
159 nStart -= m_pResult->Rows.getLength() + 1;
161 return nStart <= row && row <= nEnd;
164 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
165 ::getMaxRow()
167 if( !m_pResult )
168 return 0;
169 long nEnd = m_pResult->StartIndex;
170 if( m_pResult->Orientation )
171 return nEnd += m_pResult->Rows.getLength() - 1;
172 else
173 return nEnd;
176 bool SAL_CALL CachedContentResultSet::CCRS_Cache
177 ::hasKnownLast()
179 if( !m_pResult )
180 return false;
182 if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
183 && m_pResult->Orientation
184 && m_pResult->Rows.getLength() )
185 return true;
187 return false;
190 bool SAL_CALL CachedContentResultSet::CCRS_Cache
191 ::hasCausedException( sal_Int32 nRow )
193 if( !m_pResult )
194 return false;
195 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
196 return false;
198 long nEnd = m_pResult->StartIndex;
199 if( m_pResult->Orientation )
200 nEnd += m_pResult->Rows.getLength();
202 return nRow == nEnd+1;
205 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
206 ::getRowAny( sal_Int32 nRow )
207 throw( SQLException,
208 RuntimeException )
210 if( !nRow )
211 throw SQLException();
212 if( !m_pResult )
213 throw SQLException();
214 if( !hasRow( nRow ) )
215 throw SQLException();
217 long nDiff = nRow - m_pResult->StartIndex;
218 if( nDiff < 0 )
219 nDiff *= -1;
221 return (m_pResult->Rows)[nDiff];
224 void SAL_CALL CachedContentResultSet::CCRS_Cache
225 ::remindMapped( sal_Int32 nRow )
227 //remind that this row was mapped
228 if( !m_pResult )
229 return;
230 long nDiff = nRow - m_pResult->StartIndex;
231 if( nDiff < 0 )
232 nDiff *= -1;
233 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
234 if( nDiff < pMappedReminder->getLength() )
235 (*pMappedReminder)[nDiff] = sal_True;
238 bool SAL_CALL CachedContentResultSet::CCRS_Cache
239 ::isRowMapped( sal_Int32 nRow )
241 if( !m_pMappedReminder || !m_pResult )
242 return false;
243 long nDiff = nRow - m_pResult->StartIndex;
244 if( nDiff < 0 )
245 nDiff *= -1;
246 if( nDiff < m_pMappedReminder->getLength() )
247 return (*m_pMappedReminder)[nDiff];
248 return false;
251 void SAL_CALL CachedContentResultSet::CCRS_Cache
252 ::clearMappedReminder()
254 delete m_pMappedReminder;
255 m_pMappedReminder = NULL;
258 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
259 ::getMappedReminder()
261 if( !m_pMappedReminder )
263 sal_Int32 nCount = m_pResult->Rows.getLength();
264 m_pMappedReminder = new Sequence< sal_Bool >( nCount );
265 for( ;nCount; nCount-- )
266 (*m_pMappedReminder)[nCount] = sal_False;
268 return m_pMappedReminder;
271 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
272 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
273 throw( SQLException,
274 RuntimeException )
276 if( !nColumnIndex )
277 throw SQLException();
278 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
280 Any& rRow = getRowAny( nRow );
281 Sequence< Any > aValue;
282 rRow >>= aValue;
283 if( m_xContentIdentifierMapping->mapRow( aValue ) )
285 rRow <<= aValue;
286 remindMapped( nRow );
288 else
289 m_xContentIdentifierMapping.clear();
291 const Sequence< Any >& rRow =
292 (* static_cast< const Sequence< Any > * >
293 (getRowAny( nRow ).getValue() ));
295 if( nColumnIndex > rRow.getLength() )
296 throw SQLException();
297 return rRow[nColumnIndex-1];
300 const OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
301 ::getContentIdentifierString( sal_Int32 nRow )
302 throw( com::sun::star::uno::RuntimeException )
306 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
308 Any& rRow = getRowAny( nRow );
309 OUString aValue;
310 rRow >>= aValue;
311 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
312 remindMapped( nRow );
314 return (* static_cast< const OUString * >
315 (getRowAny( nRow ).getValue() ));
317 catch(const SQLException&)
319 throw RuntimeException();
323 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
324 ::getContentIdentifier( sal_Int32 nRow )
325 throw( com::sun::star::uno::RuntimeException )
329 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
331 Any& rRow = getRowAny( nRow );
332 Reference< XContentIdentifier > aValue;
333 rRow >>= aValue;
334 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
335 remindMapped( nRow );
337 return (* static_cast< const Reference< XContentIdentifier > * >
338 (getRowAny( nRow ).getValue() ));
340 catch(const SQLException&)
342 throw RuntimeException();
346 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
347 ::getContent( sal_Int32 nRow )
348 throw( com::sun::star::uno::RuntimeException )
352 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
354 Any& rRow = getRowAny( nRow );
355 Reference< XContent > aValue;
356 rRow >>= aValue;
357 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
358 remindMapped( nRow );
360 return (* static_cast< const Reference< XContent > * >
361 (getRowAny( nRow ).getValue() ));
363 catch (const SQLException&)
365 throw RuntimeException();
371 // class CCRS_PropertySetInfo
375 class CCRS_PropertySetInfo :
376 public cppu::OWeakObject,
377 public com::sun::star::lang::XTypeProvider,
378 public com::sun::star::beans::XPropertySetInfo
380 friend class CachedContentResultSet;
382 //my Properties
383 Sequence< com::sun::star::beans::Property >*
384 m_pProperties;
386 //some helping variables ( names for my special properties )
387 static OUString m_aPropertyNameForCount;
388 static OUString m_aPropertyNameForFinalCount;
389 static OUString m_aPropertyNameForFetchSize;
390 static OUString m_aPropertyNameForFetchDirection;
392 long m_nFetchSizePropertyHandle;
393 long m_nFetchDirectionPropertyHandle;
395 private:
396 sal_Int32 SAL_CALL
397 impl_getRemainedHandle() const;
399 bool SAL_CALL
400 impl_queryProperty(
401 const OUString& rName
402 , com::sun::star::beans::Property& rProp ) const;
403 sal_Int32 SAL_CALL
404 impl_getPos( const OUString& rName ) const;
406 static bool SAL_CALL
407 impl_isMyPropertyName( const OUString& rName );
409 public:
410 CCRS_PropertySetInfo( Reference<
411 XPropertySetInfo > xPropertySetInfoOrigin );
413 virtual ~CCRS_PropertySetInfo();
415 // XInterface
416 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType )
417 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
418 virtual void SAL_CALL acquire()
419 throw() SAL_OVERRIDE;
420 virtual void SAL_CALL release()
421 throw() SAL_OVERRIDE;
423 // XTypeProvider
424 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId()
425 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
426 virtual css::uno::Sequence< com::sun::star::uno::Type > SAL_CALL getTypes()
427 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
429 // XPropertySetInfo
430 virtual Sequence< com::sun::star::beans::Property > SAL_CALL
431 getProperties()
432 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
434 virtual com::sun::star::beans::Property SAL_CALL
435 getPropertyByName( const OUString& aName )
436 throw( com::sun::star::beans::UnknownPropertyException, RuntimeException, std::exception ) SAL_OVERRIDE;
438 virtual sal_Bool SAL_CALL
439 hasPropertyByName( const OUString& Name )
440 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
443 OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( "RowCount" );
444 OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( "IsRowCountFinal" );
445 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( "FetchSize" );
446 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( "FetchDirection" );
448 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
449 Reference< XPropertySetInfo > xInfo )
450 : m_pProperties( NULL )
451 , m_nFetchSizePropertyHandle( -1 )
452 , m_nFetchDirectionPropertyHandle( -1 )
454 //initialize list of properties:
456 // it is required, that the received xInfo contains the two
457 // properties with names 'm_aPropertyNameForCount' and
458 // 'm_aPropertyNameForFinalCount'
460 if( xInfo.is() )
462 Sequence<Property> aProps = xInfo->getProperties();
463 m_pProperties = new Sequence<Property> ( aProps );
465 else
467 OSL_FAIL( "The received XPropertySetInfo doesn't contain required properties" );
468 m_pProperties = new Sequence<Property>;
471 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
472 sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
473 sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
474 sal_Int32 nDeleted = 0;
475 if( nFetchSize != -1 )
476 nDeleted++;
477 if( nFetchDirection != -1 )
478 nDeleted++;
480 boost::scoped_ptr<Sequence< Property > > pOrigProps(new Sequence<Property> ( *m_pProperties ));
481 sal_Int32 nOrigProps = pOrigProps->getLength();
483 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
484 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
486 if( n == nFetchSize || n == nFetchDirection )
487 m--;
488 else
489 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
492 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
493 rMyProp.Name = m_aPropertyNameForFetchSize;
494 rMyProp.Type = cppu::UnoType<sal_Int32>::get();
495 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
497 if( nFetchSize != -1 )
498 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
499 else
500 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
502 rMyProp.Handle = m_nFetchSizePropertyHandle;
506 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
507 rMyProp.Name = m_aPropertyNameForFetchDirection;
508 rMyProp.Type = cppu::UnoType<sal_Bool>::get();
509 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
511 if( nFetchDirection != -1 )
512 m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
513 else
514 m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
516 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
520 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
522 delete m_pProperties;
526 // XInterface methods.
528 void SAL_CALL CCRS_PropertySetInfo::acquire()
529 throw()
531 OWeakObject::acquire();
534 void SAL_CALL CCRS_PropertySetInfo::release()
535 throw()
537 OWeakObject::release();
540 css::uno::Any SAL_CALL CCRS_PropertySetInfo::queryInterface( const css::uno::Type & rType )
541 throw( css::uno::RuntimeException, std::exception )
543 css::uno::Any aRet = cppu::queryInterface( rType,
544 (static_cast< XTypeProvider* >(this)),
545 (static_cast< XPropertySetInfo* >(this))
547 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
550 // XTypeProvider methods.
552 //list all interfaces exclusive baseclasses
553 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
554 , XTypeProvider
555 , XPropertySetInfo
558 // XPropertySetInfo methods.
560 //virtual
561 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
562 ::getProperties() throw( RuntimeException, std::exception )
564 return *m_pProperties;
567 //virtual
568 Property SAL_CALL CCRS_PropertySetInfo
569 ::getPropertyByName( const OUString& aName )
570 throw( UnknownPropertyException, RuntimeException, std::exception )
572 if ( aName.isEmpty() )
573 throw UnknownPropertyException();
575 Property aProp;
576 if ( impl_queryProperty( aName, aProp ) )
577 return aProp;
579 throw UnknownPropertyException();
582 //virtual
583 sal_Bool SAL_CALL CCRS_PropertySetInfo
584 ::hasPropertyByName( const OUString& Name )
585 throw( RuntimeException, std::exception )
587 return ( impl_getPos( Name ) != -1 );
591 // impl_ methods.
594 sal_Int32 SAL_CALL CCRS_PropertySetInfo
595 ::impl_getPos( const OUString& rName ) const
597 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
599 const Property& rMyProp = (*m_pProperties)[nN];
600 if( rMyProp.Name == rName )
601 return nN;
603 return -1;
606 bool SAL_CALL CCRS_PropertySetInfo
607 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
609 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
611 const Property& rMyProp = (*m_pProperties)[nN];
612 if( rMyProp.Name == rName )
614 rProp.Name = rMyProp.Name;
615 rProp.Handle = rMyProp.Handle;
616 rProp.Type = rMyProp.Type;
617 rProp.Attributes = rMyProp.Attributes;
619 return true;
622 return false;
625 //static
626 bool SAL_CALL CCRS_PropertySetInfo
627 ::impl_isMyPropertyName( const OUString& rPropertyName )
629 return ( rPropertyName == m_aPropertyNameForCount
630 || rPropertyName == m_aPropertyNameForFinalCount
631 || rPropertyName == m_aPropertyNameForFetchSize
632 || rPropertyName == m_aPropertyNameForFetchDirection );
635 sal_Int32 SAL_CALL CCRS_PropertySetInfo
636 ::impl_getRemainedHandle( ) const
638 sal_Int32 nHandle = 1;
640 if( !m_pProperties )
642 OSL_FAIL( "Properties not initialized yet" );
643 return nHandle;
645 bool bFound = true;
646 while( bFound )
648 bFound = false;
649 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
651 if( nHandle == (*m_pProperties)[nN].Handle )
653 bFound = true;
654 nHandle++;
655 break;
659 return nHandle;
664 // class CachedContentResultSet
668 CachedContentResultSet::CachedContentResultSet(
669 const Reference< XComponentContext > & rxContext
670 , const Reference< XResultSet > & xOrigin
671 , const Reference< XContentIdentifierMapping > &
672 xContentIdentifierMapping )
673 : ContentResultSetWrapper( xOrigin )
675 , m_xContext( rxContext )
676 , m_xFetchProvider( NULL )
677 , m_xFetchProviderForContentAccess( NULL )
679 , m_xMyPropertySetInfo( NULL )
680 , m_pMyPropSetInfo( NULL )
682 , m_xContentIdentifierMapping( xContentIdentifierMapping )
683 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
684 , m_bAfterLast( false )
685 , m_nLastAppliedPos( 0 )
686 , m_bAfterLastApplied( false )
687 , m_nKnownCount( 0 )
688 , m_bFinalCount( false )
689 , m_nFetchSize(
690 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
691 , m_nFetchDirection(
692 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
694 , m_bLastReadWasFromCache( false )
695 , m_bLastCachedReadWasNull( true )
696 , m_aCache( m_xContentIdentifierMapping )
697 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
698 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
699 , m_aCacheContent( m_xContentIdentifierMapping )
700 , m_bTriedToGetTypeConverter( false )
701 , m_xTypeConverter( NULL )
703 m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
704 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
706 m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
707 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
709 impl_init();
712 CachedContentResultSet::~CachedContentResultSet()
714 impl_deinit();
715 //do not delete m_pMyPropSetInfo, cause it is hold via reference
719 // impl_ methods.
722 bool SAL_CALL CachedContentResultSet
723 ::applyPositionToOrigin( sal_Int32 nRow )
724 throw( SQLException,
725 RuntimeException )
727 impl_EnsureNotDisposed();
730 @returns
731 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
732 the result set.
735 ReacquireableGuard aGuard( m_aMutex );
736 OSL_ENSURE( nRow >= 0, "only positive values supported" );
737 if( !m_xResultSetOrigin.is() )
739 OSL_FAIL( "broadcaster was disposed already" );
740 return false;
742 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
744 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
745 bool bAfterLastApplied = m_bAfterLastApplied;
746 bool bAfterLast = m_bAfterLast;
747 sal_Int32 nForwardOnly = m_nForwardOnly;
749 aGuard.clear();
751 if( bAfterLastApplied || nLastAppliedPos != nRow )
753 if( nForwardOnly == 1 )
755 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
756 throw SQLException();
758 sal_Int32 nN = nRow - nLastAppliedPos;
759 sal_Int32 nM;
760 for( nM = 0; nN--; nM++ )
762 if( !m_xResultSetOrigin->next() )
763 break;
766 aGuard.reacquire();
767 m_nLastAppliedPos += nM;
768 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
769 return nRow == m_nLastAppliedPos;
772 if( !nRow ) //absolute( 0 ) will throw exception
774 m_xResultSetOrigin->beforeFirst();
776 aGuard.reacquire();
777 m_nLastAppliedPos = 0;
778 m_bAfterLastApplied = false;
779 return false;
783 //move absolute, if !nLastAppliedPos
784 //because move relative would throw exception
785 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
787 bool bValid = m_xResultSetOrigin->absolute( nRow );
789 aGuard.reacquire();
790 m_nLastAppliedPos = nRow;
791 m_bAfterLastApplied = !bValid;
792 return bValid;
794 else
796 bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
798 aGuard.reacquire();
799 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
800 m_bAfterLastApplied = !bValid;
801 return bValid;
804 catch (const SQLException&)
806 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
808 sal_Int32 nN = nRow - nLastAppliedPos;
809 sal_Int32 nM;
810 for( nM = 0; nN--; nM++ )
812 if( !m_xResultSetOrigin->next() )
813 break;
816 aGuard.reacquire();
817 m_nLastAppliedPos += nM;
818 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
820 else
821 throw;
824 return nRow == m_nLastAppliedPos;
826 return true;
831 //define for fetching data
835 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
836 bool bDirection = !!( \
837 nFetchDirection != FetchDirection::REVERSE ); \
838 FetchResult aResult = \
839 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
840 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
841 aCache.loadData( aResult ); \
842 sal_Int32 nMax = aCache.getMaxRow(); \
843 sal_Int32 nCurCount = m_nKnownCount; \
844 bool bIsFinalCount = aCache.hasKnownLast(); \
845 bool bCurIsFinalCount = m_bFinalCount; \
846 aGuard2.clear(); \
847 if( nMax > nCurCount ) \
848 impl_changeRowCount( nCurCount, nMax ); \
849 if( bIsFinalCount && !bCurIsFinalCount ) \
850 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
852 void SAL_CALL CachedContentResultSet
853 ::impl_fetchData( sal_Int32 nRow
854 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
855 throw( com::sun::star::uno::RuntimeException )
857 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
860 void SAL_CALL CachedContentResultSet
861 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
863 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
864 if( nNew <= nOld )
865 return;
867 //create PropertyChangeEvent and set value
868 PropertyChangeEvent aEvt;
870 osl::Guard< osl::Mutex > aGuard( m_aMutex );
871 aEvt.Source = static_cast< XPropertySet * >( this );
872 aEvt.Further = sal_False;
873 aEvt.OldValue <<= nOld;
874 aEvt.NewValue <<= nNew;
876 m_nKnownCount = nNew;
879 //send PropertyChangeEvent to listeners
880 impl_notifyPropertyChangeListeners( aEvt );
883 void SAL_CALL CachedContentResultSet
884 ::impl_changeIsRowCountFinal( bool bOld, bool bNew )
886 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
887 if( ! (!bOld && bNew ) )
888 return;
890 //create PropertyChangeEvent and set value
891 PropertyChangeEvent aEvt;
893 osl::Guard< osl::Mutex > aGuard( m_aMutex );
894 aEvt.Source = static_cast< XPropertySet * >( this );
895 aEvt.Further = sal_False;
896 aEvt.OldValue <<= bOld;
897 aEvt.NewValue <<= bNew;
899 m_bFinalCount = bNew;
902 //send PropertyChangeEvent to listeners
903 impl_notifyPropertyChangeListeners( aEvt );
906 bool SAL_CALL CachedContentResultSet
907 ::impl_isKnownValidPosition( sal_Int32 nRow )
909 return m_nKnownCount && nRow
910 && nRow <= m_nKnownCount;
913 bool SAL_CALL CachedContentResultSet
914 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
916 if( !nRow )
917 return true;
918 if( !m_bFinalCount )
919 return false;
920 return nRow > m_nKnownCount;
924 //virtual
925 void SAL_CALL CachedContentResultSet
926 ::impl_initPropertySetInfo()
928 ContentResultSetWrapper::impl_initPropertySetInfo();
930 osl::Guard< osl::Mutex > aGuard( m_aMutex );
931 if( m_pMyPropSetInfo )
932 return;
933 m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
934 m_xMyPropertySetInfo = m_pMyPropSetInfo;
935 m_xPropertySetInfo = m_xMyPropertySetInfo;
939 // XInterface methods.
940 void SAL_CALL CachedContentResultSet::acquire()
941 throw()
943 OWeakObject::acquire();
946 void SAL_CALL CachedContentResultSet::release()
947 throw()
949 OWeakObject::release();
952 Any SAL_CALL CachedContentResultSet
953 ::queryInterface( const Type& rType )
954 throw ( RuntimeException, std::exception )
956 //list all interfaces inclusive baseclasses of interfaces
958 Any aRet = ContentResultSetWrapper::queryInterface( rType );
959 if( aRet.hasValue() )
960 return aRet;
962 aRet = cppu::queryInterface( rType,
963 static_cast< XTypeProvider* >( this ),
964 static_cast< XServiceInfo* >( this ) );
966 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
970 // XTypeProvider methods.
972 //list all interfaces exclusive baseclasses
973 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
974 , XTypeProvider
975 , XServiceInfo
976 , XComponent
977 , XCloseable
978 , XResultSetMetaDataSupplier
979 , XPropertySet
981 , XPropertyChangeListener
982 , XVetoableChangeListener
984 , XContentAccess
986 , XResultSet
987 , XRow );
990 // XServiceInfo methods.
993 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
994 OUString(
995 "com.sun.star.comp.ucb.CachedContentResultSet" ),
996 CACHED_CONTENT_RESULTSET_SERVICE_NAME );
999 // XPropertySet methods. ( inherited )
1002 // virtual
1003 void SAL_CALL CachedContentResultSet
1004 ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1005 throw( UnknownPropertyException,
1006 PropertyVetoException,
1007 IllegalArgumentException,
1008 WrappedTargetException,
1009 RuntimeException, std::exception )
1011 impl_EnsureNotDisposed();
1013 if( !getPropertySetInfo().is() )
1015 OSL_FAIL( "broadcaster was disposed already" );
1016 throw UnknownPropertyException();
1019 Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
1020 //throws UnknownPropertyException, if so
1022 if( aProp.Attributes & PropertyAttribute::READONLY )
1024 //It is assumed, that the properties
1025 //'RowCount' and 'IsRowCountFinal' are readonly!
1026 throw IllegalArgumentException();
1028 if( aProp.Name == CCRS_PropertySetInfo
1029 ::m_aPropertyNameForFetchDirection )
1031 //check value
1032 sal_Int32 nNew;
1033 if( !( aValue >>= nNew ) )
1035 throw IllegalArgumentException();
1038 if( nNew == FetchDirection::UNKNOWN )
1040 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1042 else if( !( nNew == FetchDirection::FORWARD
1043 || nNew == FetchDirection::REVERSE ) )
1045 throw IllegalArgumentException();
1048 //create PropertyChangeEvent and set value
1049 PropertyChangeEvent aEvt;
1051 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1052 aEvt.Source = static_cast< XPropertySet * >( this );
1053 aEvt.PropertyName = aPropertyName;
1054 aEvt.Further = sal_False;
1055 aEvt.PropertyHandle = m_pMyPropSetInfo->
1056 m_nFetchDirectionPropertyHandle;
1057 aEvt.OldValue <<= m_nFetchDirection;
1058 aEvt.NewValue <<= nNew;
1060 m_nFetchDirection = nNew;
1063 //send PropertyChangeEvent to listeners
1064 impl_notifyPropertyChangeListeners( aEvt );
1066 else if( aProp.Name == CCRS_PropertySetInfo
1067 ::m_aPropertyNameForFetchSize )
1069 //check value
1070 sal_Int32 nNew;
1071 if( !( aValue >>= nNew ) )
1073 throw IllegalArgumentException();
1076 if( nNew < 0 )
1078 nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1081 //create PropertyChangeEvent and set value
1082 PropertyChangeEvent aEvt;
1084 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1085 aEvt.Source = static_cast< XPropertySet * >( this );
1086 aEvt.PropertyName = aPropertyName;
1087 aEvt.Further = sal_False;
1088 aEvt.PropertyHandle = m_pMyPropSetInfo->
1089 m_nFetchSizePropertyHandle;
1090 aEvt.OldValue <<= m_nFetchSize;
1091 aEvt.NewValue <<= nNew;
1093 m_nFetchSize = nNew;
1096 //send PropertyChangeEvent to listeners
1097 impl_notifyPropertyChangeListeners( aEvt );
1099 else
1101 impl_init_xPropertySetOrigin();
1103 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1104 if( !m_xPropertySetOrigin.is() )
1106 OSL_FAIL( "broadcaster was disposed already" );
1107 return;
1110 m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1115 // virtual
1116 Any SAL_CALL CachedContentResultSet
1117 ::getPropertyValue( const OUString& rPropertyName )
1118 throw( UnknownPropertyException,
1119 WrappedTargetException,
1120 RuntimeException, std::exception )
1122 impl_EnsureNotDisposed();
1124 if( !getPropertySetInfo().is() )
1126 OSL_FAIL( "broadcaster was disposed already" );
1127 throw UnknownPropertyException();
1130 Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1131 //throws UnknownPropertyException, if so
1133 Any aValue;
1134 if( rPropertyName == CCRS_PropertySetInfo
1135 ::m_aPropertyNameForCount )
1137 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1138 aValue <<= m_nKnownCount;
1140 else if( rPropertyName == CCRS_PropertySetInfo
1141 ::m_aPropertyNameForFinalCount )
1143 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1144 aValue <<= m_bFinalCount;
1146 else if( rPropertyName == CCRS_PropertySetInfo
1147 ::m_aPropertyNameForFetchSize )
1149 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1150 aValue <<= m_nFetchSize;
1152 else if( rPropertyName == CCRS_PropertySetInfo
1153 ::m_aPropertyNameForFetchDirection )
1155 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1156 aValue <<= m_nFetchDirection;
1158 else
1160 impl_init_xPropertySetOrigin();
1162 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1163 if( !m_xPropertySetOrigin.is() )
1165 OSL_FAIL( "broadcaster was disposed already" );
1166 throw UnknownPropertyException();
1169 aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1171 return aValue;
1175 // own methods. ( inherited )
1178 //virtual
1179 void SAL_CALL CachedContentResultSet
1180 ::impl_disposing( const EventObject& rEventObject )
1181 throw( RuntimeException )
1184 impl_EnsureNotDisposed();
1185 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1186 //release all references to the broadcaster:
1187 m_xFetchProvider.clear();
1188 m_xFetchProviderForContentAccess.clear();
1190 ContentResultSetWrapper::impl_disposing( rEventObject );
1193 //virtual
1194 void SAL_CALL CachedContentResultSet
1195 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1196 throw( RuntimeException )
1198 impl_EnsureNotDisposed();
1200 PropertyChangeEvent aEvt( rEvt );
1201 aEvt.Source = static_cast< XPropertySet * >( this );
1202 aEvt.Further = sal_False;
1205 if( CCRS_PropertySetInfo
1206 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1208 //don't notify foreign events on fetchsize and fetchdirection
1209 if( aEvt.PropertyName == CCRS_PropertySetInfo
1210 ::m_aPropertyNameForFetchSize
1211 || aEvt.PropertyName == CCRS_PropertySetInfo
1212 ::m_aPropertyNameForFetchDirection )
1213 return;
1215 //adjust my props 'RowCount' and 'IsRowCountFinal'
1216 if( aEvt.PropertyName == CCRS_PropertySetInfo
1217 ::m_aPropertyNameForCount )
1218 {//RowCount changed
1220 //check value
1221 sal_Int32 nNew = 0;
1222 if( !( aEvt.NewValue >>= nNew ) )
1224 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1225 return;
1228 impl_changeRowCount( m_nKnownCount, nNew );
1230 else if( aEvt.PropertyName == CCRS_PropertySetInfo
1231 ::m_aPropertyNameForFinalCount )
1232 {//IsRowCountFinal changed
1234 //check value
1235 bool bNew = false;
1236 if( !( aEvt.NewValue >>= bNew ) )
1238 OSL_FAIL( "PropertyChangeEvent contains wrong data" );
1239 return;
1241 impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1243 return;
1247 impl_notifyPropertyChangeListeners( aEvt );
1251 //virtual
1252 void SAL_CALL CachedContentResultSet
1253 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1254 throw( PropertyVetoException,
1255 RuntimeException )
1257 impl_EnsureNotDisposed();
1259 //don't notify events on my properties, cause they are not vetoable
1260 if( CCRS_PropertySetInfo
1261 ::impl_isMyPropertyName( rEvt.PropertyName ) )
1263 return;
1267 PropertyChangeEvent aEvt( rEvt );
1268 aEvt.Source = static_cast< XPropertySet * >( this );
1269 aEvt.Further = sal_False;
1271 impl_notifyVetoableChangeListeners( aEvt );
1275 // XContentAccess methods. ( inherited ) ( -- position dependent )
1278 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE ) \
1279 impl_EnsureNotDisposed(); \
1280 ReacquireableGuard aGuard( m_aMutex ); \
1281 sal_Int32 nRow = m_nRow; \
1282 sal_Int32 nFetchSize = m_nFetchSize; \
1283 sal_Int32 nFetchDirection = m_nFetchDirection; \
1284 if( !m_aCache##XXX.hasRow( nRow ) ) \
1286 try \
1288 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1290 if( !m_xFetchProviderForContentAccess.is() ) \
1292 OSL_FAIL( "broadcaster was disposed already" ); \
1293 throw RuntimeException(); \
1295 aGuard.clear(); \
1296 if( impl_isForwardOnly() ) \
1297 applyPositionToOrigin( nRow ); \
1299 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1301 aGuard.reacquire(); \
1302 if( !m_aCache##XXX.hasRow( nRow ) ) \
1304 aGuard.clear(); \
1305 applyPositionToOrigin( nRow ); \
1306 TYPE aRet = ContentResultSetWrapper::queryXXX();\
1307 if( m_xContentIdentifierMapping.is() ) \
1308 return m_xContentIdentifierMapping->map##XXX( aRet );\
1309 return aRet; \
1312 catch (const RuntimeException&) \
1314 throw; \
1316 catch (const Exception& e) \
1318 Any a(cppu::getCaughtException()); \
1319 throw WrappedTargetRuntimeException( \
1320 "wrapped Exception " + e.Message, \
1321 Reference<XInterface>(), a); \
1324 return m_aCache##XXX.get##XXX( nRow );
1326 // virtual
1327 OUString SAL_CALL CachedContentResultSet
1328 ::queryContentIdentifierString()
1329 throw( RuntimeException, std::exception )
1331 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1335 // virtual
1336 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1337 ::queryContentIdentifier()
1338 throw( RuntimeException, std::exception )
1340 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1344 // virtual
1345 Reference< XContent > SAL_CALL CachedContentResultSet
1346 ::queryContent()
1347 throw( RuntimeException, std::exception )
1349 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1353 // XResultSet methods. ( inherited )
1355 //virtual
1357 sal_Bool SAL_CALL CachedContentResultSet
1358 ::next()
1359 throw( SQLException,
1360 RuntimeException, std::exception )
1362 impl_EnsureNotDisposed();
1364 ReacquireableGuard aGuard( m_aMutex );
1365 //after last
1366 if( m_bAfterLast )
1367 return sal_False;
1368 //last
1369 aGuard.clear();
1370 if( isLast() )
1372 aGuard.reacquire();
1373 m_nRow++;
1374 m_bAfterLast = true;
1375 return sal_False;
1377 aGuard.reacquire();
1378 //known valid position
1379 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1381 m_nRow++;
1382 return sal_True;
1385 //unknown position
1386 sal_Int32 nRow = m_nRow;
1387 aGuard.clear();
1389 bool bValid = applyPositionToOrigin( nRow + 1 );
1391 aGuard.reacquire();
1392 m_nRow = nRow + 1;
1393 m_bAfterLast = !bValid;
1394 return bValid;
1397 //virtual
1398 sal_Bool SAL_CALL CachedContentResultSet
1399 ::previous()
1400 throw( SQLException,
1401 RuntimeException, std::exception )
1403 impl_EnsureNotDisposed();
1405 if( impl_isForwardOnly() )
1406 throw SQLException();
1408 ReacquireableGuard aGuard( m_aMutex );
1409 //before first ?:
1410 if( !m_bAfterLast && !m_nRow )
1411 return sal_False;
1412 //first ?:
1413 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1415 m_nRow--;
1416 m_bAfterLast = false;
1417 return sal_False;
1419 //known valid position ?:
1420 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1422 m_nRow--;
1423 m_bAfterLast = false;
1424 return sal_True;
1426 //unknown position:
1427 sal_Int32 nRow = m_nRow;
1428 aGuard.clear();
1430 bool bValid = applyPositionToOrigin( nRow - 1 );
1432 aGuard.reacquire();
1433 m_nRow = nRow - 1;
1434 m_bAfterLast = false;
1435 return bValid;
1438 //virtual
1439 sal_Bool SAL_CALL CachedContentResultSet
1440 ::absolute( sal_Int32 row )
1441 throw( SQLException,
1442 RuntimeException, std::exception )
1444 impl_EnsureNotDisposed();
1446 if( !row )
1447 throw SQLException();
1449 if( impl_isForwardOnly() )
1450 throw SQLException();
1452 ReacquireableGuard aGuard( m_aMutex );
1454 if( !m_xResultSetOrigin.is() )
1456 OSL_FAIL( "broadcaster was disposed already" );
1457 return sal_False;
1459 if( row < 0 )
1461 if( m_bFinalCount )
1463 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1464 bool bValid = true;
1465 if( nNewRow <= 0 )
1467 nNewRow = 0;
1468 bValid = false;
1470 m_nRow = nNewRow;
1471 m_bAfterLast = false;
1472 return bValid;
1474 //unknown final count:
1475 aGuard.clear();
1477 // Solaris has problems catching or propagating derived exceptions
1478 // when only the base class is known, so make ResultSetException
1479 // (derived from SQLException) known here:
1480 bool bValid;
1483 bValid = m_xResultSetOrigin->absolute( row );
1485 catch (const ResultSetException&)
1487 throw;
1490 aGuard.reacquire();
1491 if( m_bFinalCount )
1493 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1494 if( nNewRow < 0 )
1495 nNewRow = 0;
1496 m_nLastAppliedPos = nNewRow;
1497 m_nRow = nNewRow;
1498 m_bAfterLastApplied = m_bAfterLast = false;
1499 return bValid;
1501 aGuard.clear();
1503 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1505 aGuard.reacquire();
1506 m_nLastAppliedPos = nCurRow;
1507 m_nRow = nCurRow;
1508 m_bAfterLast = false;
1509 return nCurRow != 0;
1511 //row > 0:
1512 if( m_bFinalCount )
1514 if( row > m_nKnownCount )
1516 m_nRow = m_nKnownCount + 1;
1517 m_bAfterLast = true;
1518 return sal_False;
1520 m_nRow = row;
1521 m_bAfterLast = false;
1522 return sal_True;
1524 //unknown new position:
1525 aGuard.clear();
1527 bool bValid = m_xResultSetOrigin->absolute( row );
1529 aGuard.reacquire();
1530 if( m_bFinalCount )
1532 sal_Int32 nNewRow = row;
1533 if( nNewRow > m_nKnownCount )
1535 nNewRow = m_nKnownCount + 1;
1536 m_bAfterLastApplied = m_bAfterLast = true;
1538 else
1539 m_bAfterLastApplied = m_bAfterLast = false;
1541 m_nLastAppliedPos = nNewRow;
1542 m_nRow = nNewRow;
1543 return bValid;
1545 aGuard.clear();
1547 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1548 bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1550 aGuard.reacquire();
1551 m_nLastAppliedPos = nCurRow;
1552 m_nRow = nCurRow;
1553 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1554 return nCurRow && !bIsAfterLast;
1557 //virtual
1558 sal_Bool SAL_CALL CachedContentResultSet
1559 ::relative( sal_Int32 rows )
1560 throw( SQLException,
1561 RuntimeException, std::exception )
1563 impl_EnsureNotDisposed();
1565 if( impl_isForwardOnly() )
1566 throw SQLException();
1568 ReacquireableGuard aGuard( m_aMutex );
1569 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1570 throw SQLException();
1572 if( !rows )
1573 return sal_True;
1575 sal_Int32 nNewRow = m_nRow + rows;
1576 if( nNewRow < 0 )
1577 nNewRow = 0;
1579 if( impl_isKnownValidPosition( nNewRow ) )
1581 m_nRow = nNewRow;
1582 m_bAfterLast = false;
1583 return sal_True;
1585 else
1587 //known invalid new position:
1588 if( nNewRow == 0 )
1590 m_bAfterLast = false;
1591 m_nRow = 0;
1592 return sal_False;
1594 if( m_bFinalCount && nNewRow > m_nKnownCount )
1596 m_bAfterLast = true;
1597 m_nRow = m_nKnownCount + 1;
1598 return sal_False;
1600 //unknown new position:
1601 aGuard.clear();
1602 bool bValid = applyPositionToOrigin( nNewRow );
1604 aGuard.reacquire();
1605 m_nRow = nNewRow;
1606 m_bAfterLast = !bValid && nNewRow > 0;
1607 return bValid;
1612 //virtual
1613 sal_Bool SAL_CALL CachedContentResultSet
1614 ::first()
1615 throw( SQLException,
1616 RuntimeException, std::exception )
1618 impl_EnsureNotDisposed();
1620 if( impl_isForwardOnly() )
1621 throw SQLException();
1623 ReacquireableGuard aGuard( m_aMutex );
1624 if( impl_isKnownValidPosition( 1 ) )
1626 m_nRow = 1;
1627 m_bAfterLast = false;
1628 return sal_True;
1630 if( impl_isKnownInvalidPosition( 1 ) )
1632 m_nRow = 1;
1633 m_bAfterLast = false;
1634 return sal_False;
1636 //unknown position
1637 aGuard.clear();
1639 bool bValid = applyPositionToOrigin( 1 );
1641 aGuard.reacquire();
1642 m_nRow = 1;
1643 m_bAfterLast = false;
1644 return bValid;
1647 //virtual
1648 sal_Bool SAL_CALL CachedContentResultSet
1649 ::last()
1650 throw( SQLException,
1651 RuntimeException, std::exception )
1653 impl_EnsureNotDisposed();
1655 if( impl_isForwardOnly() )
1656 throw SQLException();
1658 ReacquireableGuard aGuard( m_aMutex );
1659 if( m_bFinalCount )
1661 m_nRow = m_nKnownCount;
1662 m_bAfterLast = false;
1663 return m_nKnownCount != 0;
1665 //unknown position
1666 if( !m_xResultSetOrigin.is() )
1668 OSL_FAIL( "broadcaster was disposed already" );
1669 return sal_False;
1671 aGuard.clear();
1673 bool bValid = m_xResultSetOrigin->last();
1675 aGuard.reacquire();
1676 m_bAfterLastApplied = m_bAfterLast = false;
1677 if( m_bFinalCount )
1679 m_nLastAppliedPos = m_nKnownCount;
1680 m_nRow = m_nKnownCount;
1681 return bValid;
1683 aGuard.clear();
1685 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1687 aGuard.reacquire();
1688 m_nLastAppliedPos = nCurRow;
1689 m_nRow = nCurRow;
1690 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1691 m_nKnownCount = nCurRow;
1692 m_bFinalCount = true;
1693 return nCurRow != 0;
1696 //virtual
1697 void SAL_CALL CachedContentResultSet
1698 ::beforeFirst()
1699 throw( SQLException,
1700 RuntimeException, std::exception )
1702 impl_EnsureNotDisposed();
1704 if( impl_isForwardOnly() )
1705 throw SQLException();
1707 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1708 m_nRow = 0;
1709 m_bAfterLast = false;
1712 //virtual
1713 void SAL_CALL CachedContentResultSet
1714 ::afterLast()
1715 throw( SQLException,
1716 RuntimeException, std::exception )
1718 impl_EnsureNotDisposed();
1720 if( impl_isForwardOnly() )
1721 throw SQLException();
1723 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1724 m_nRow = 1;
1725 m_bAfterLast = true;
1728 //virtual
1729 sal_Bool SAL_CALL CachedContentResultSet
1730 ::isAfterLast()
1731 throw( SQLException,
1732 RuntimeException, std::exception )
1734 impl_EnsureNotDisposed();
1736 ReacquireableGuard aGuard( m_aMutex );
1737 if( !m_bAfterLast )
1738 return sal_False;
1739 if( m_nKnownCount )
1740 return m_bAfterLast;
1741 if( m_bFinalCount )
1742 return sal_False;
1744 if( !m_xResultSetOrigin.is() )
1746 OSL_FAIL( "broadcaster was disposed already" );
1747 return sal_False;
1749 aGuard.clear();
1751 //find out whethter the original resultset contains rows or not
1752 m_xResultSetOrigin->afterLast();
1754 aGuard.reacquire();
1755 m_bAfterLastApplied = true;
1756 aGuard.clear();
1758 return m_xResultSetOrigin->isAfterLast();
1761 //virtual
1762 sal_Bool SAL_CALL CachedContentResultSet
1763 ::isBeforeFirst()
1764 throw( SQLException,
1765 RuntimeException, std::exception )
1767 impl_EnsureNotDisposed();
1769 ReacquireableGuard aGuard( m_aMutex );
1770 if( m_bAfterLast )
1771 return sal_False;
1772 if( m_nRow )
1773 return sal_False;
1774 if( m_nKnownCount )
1775 return !m_nRow;
1776 if( m_bFinalCount )
1777 return sal_False;
1779 if( !m_xResultSetOrigin.is() )
1781 OSL_FAIL( "broadcaster was disposed already" );
1782 return sal_False;
1784 aGuard.clear();
1786 //find out whethter the original resultset contains rows or not
1787 m_xResultSetOrigin->beforeFirst();
1789 aGuard.reacquire();
1790 m_bAfterLastApplied = false;
1791 m_nLastAppliedPos = 0;
1792 aGuard.clear();
1794 return m_xResultSetOrigin->isBeforeFirst();
1797 //virtual
1798 sal_Bool SAL_CALL CachedContentResultSet
1799 ::isFirst()
1800 throw( SQLException,
1801 RuntimeException, std::exception )
1803 impl_EnsureNotDisposed();
1805 sal_Int32 nRow = 0;
1806 Reference< XResultSet > xResultSetOrigin;
1809 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1810 if( m_bAfterLast )
1811 return sal_False;
1812 if( m_nRow != 1 )
1813 return sal_False;
1814 if( m_nKnownCount )
1815 return m_nRow == 1;
1816 if( m_bFinalCount )
1817 return sal_False;
1819 nRow = m_nRow;
1820 xResultSetOrigin = m_xResultSetOrigin;
1823 //need to ask origin
1825 if( applyPositionToOrigin( nRow ) )
1826 return xResultSetOrigin->isFirst();
1827 else
1828 return sal_False;
1832 //virtual
1833 sal_Bool SAL_CALL CachedContentResultSet
1834 ::isLast()
1835 throw( SQLException,
1836 RuntimeException, std::exception )
1838 impl_EnsureNotDisposed();
1840 sal_Int32 nRow = 0;
1841 Reference< XResultSet > xResultSetOrigin;
1843 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1844 if( m_bAfterLast )
1845 return sal_False;
1846 if( m_nRow < m_nKnownCount )
1847 return sal_False;
1848 if( m_bFinalCount )
1849 return m_nKnownCount && m_nRow == m_nKnownCount;
1851 nRow = m_nRow;
1852 xResultSetOrigin = m_xResultSetOrigin;
1855 //need to ask origin
1857 if( applyPositionToOrigin( nRow ) )
1858 return xResultSetOrigin->isLast();
1859 else
1860 return sal_False;
1865 //virtual
1866 sal_Int32 SAL_CALL CachedContentResultSet
1867 ::getRow()
1868 throw( SQLException,
1869 RuntimeException, std::exception )
1871 impl_EnsureNotDisposed();
1873 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1874 if( m_bAfterLast )
1875 return 0;
1876 return m_nRow;
1879 //virtual
1880 void SAL_CALL CachedContentResultSet
1881 ::refreshRow()
1882 throw( SQLException,
1883 RuntimeException, std::exception )
1885 impl_EnsureNotDisposed();
1887 //the ContentResultSet is static and will not change
1888 //therefore we don't need to reload anything
1891 //virtual
1892 sal_Bool SAL_CALL CachedContentResultSet
1893 ::rowUpdated()
1894 throw( SQLException,
1895 RuntimeException, std::exception )
1897 impl_EnsureNotDisposed();
1899 //the ContentResultSet is static and will not change
1900 return sal_False;
1902 //virtual
1903 sal_Bool SAL_CALL CachedContentResultSet
1904 ::rowInserted()
1905 throw( SQLException,
1906 RuntimeException, std::exception )
1908 impl_EnsureNotDisposed();
1910 //the ContentResultSet is static and will not change
1911 return sal_False;
1914 //virtual
1915 sal_Bool SAL_CALL CachedContentResultSet
1916 ::rowDeleted()
1917 throw( SQLException,
1918 RuntimeException, std::exception )
1920 impl_EnsureNotDisposed();
1922 //the ContentResultSet is static and will not change
1923 return sal_False;
1926 //virtual
1927 Reference< XInterface > SAL_CALL CachedContentResultSet
1928 ::getStatement()
1929 throw( SQLException,
1930 RuntimeException, std::exception )
1932 impl_EnsureNotDisposed();
1933 //@todo ?return anything
1934 return Reference< XInterface >();
1938 // XRow methods. ( inherited )
1941 //virtual
1942 sal_Bool SAL_CALL CachedContentResultSet
1943 ::wasNull()
1944 throw( SQLException,
1945 RuntimeException, std::exception )
1947 impl_EnsureNotDisposed();
1948 impl_init_xRowOrigin();
1950 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1951 if( m_bLastReadWasFromCache )
1952 return m_bLastCachedReadWasNull;
1953 if( !m_xRowOrigin.is() )
1955 OSL_FAIL( "broadcaster was disposed already" );
1956 return sal_False;
1959 return m_xRowOrigin->wasNull();
1962 //virtual
1963 OUString SAL_CALL CachedContentResultSet
1964 ::getString( sal_Int32 columnIndex )
1965 throw( SQLException,
1966 RuntimeException, std::exception )
1968 return rowOriginGet<OUString>(&css::sdbc::XRow::getString, columnIndex);
1971 //virtual
1972 sal_Bool SAL_CALL CachedContentResultSet
1973 ::getBoolean( sal_Int32 columnIndex )
1974 throw( SQLException,
1975 RuntimeException, std::exception )
1977 return rowOriginGet<sal_Bool>(&css::sdbc::XRow::getBoolean, columnIndex);
1980 //virtual
1981 sal_Int8 SAL_CALL CachedContentResultSet
1982 ::getByte( sal_Int32 columnIndex )
1983 throw( SQLException,
1984 RuntimeException, std::exception )
1986 return rowOriginGet<sal_Int8>(&css::sdbc::XRow::getByte, columnIndex);
1989 //virtual
1990 sal_Int16 SAL_CALL CachedContentResultSet
1991 ::getShort( sal_Int32 columnIndex )
1992 throw( SQLException,
1993 RuntimeException, std::exception )
1995 return rowOriginGet<sal_Int16>(&css::sdbc::XRow::getShort, columnIndex);
1998 //virtual
1999 sal_Int32 SAL_CALL CachedContentResultSet
2000 ::getInt( sal_Int32 columnIndex )
2001 throw( SQLException,
2002 RuntimeException, std::exception )
2004 return rowOriginGet<sal_Int32>(&css::sdbc::XRow::getInt, columnIndex);
2007 //virtual
2008 sal_Int64 SAL_CALL CachedContentResultSet
2009 ::getLong( sal_Int32 columnIndex )
2010 throw( SQLException,
2011 RuntimeException, std::exception )
2013 return rowOriginGet<sal_Int64>(&css::sdbc::XRow::getLong, columnIndex);
2016 //virtual
2017 float SAL_CALL CachedContentResultSet
2018 ::getFloat( sal_Int32 columnIndex )
2019 throw( SQLException,
2020 RuntimeException, std::exception )
2022 return rowOriginGet<float>(&css::sdbc::XRow::getFloat, columnIndex);
2025 //virtual
2026 double SAL_CALL CachedContentResultSet
2027 ::getDouble( sal_Int32 columnIndex )
2028 throw( SQLException,
2029 RuntimeException, std::exception )
2031 return rowOriginGet<double>(&css::sdbc::XRow::getDouble, columnIndex);
2034 //virtual
2035 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
2036 ::getBytes( sal_Int32 columnIndex )
2037 throw( SQLException,
2038 RuntimeException, std::exception )
2040 return rowOriginGet< css::uno::Sequence<sal_Int8> >(
2041 &css::sdbc::XRow::getBytes, columnIndex);
2044 //virtual
2045 Date SAL_CALL CachedContentResultSet
2046 ::getDate( sal_Int32 columnIndex )
2047 throw( SQLException,
2048 RuntimeException, std::exception )
2050 return rowOriginGet<css::util::Date>(
2051 &css::sdbc::XRow::getDate, columnIndex);
2054 //virtual
2055 Time SAL_CALL CachedContentResultSet
2056 ::getTime( sal_Int32 columnIndex )
2057 throw( SQLException,
2058 RuntimeException, std::exception )
2060 return rowOriginGet<css::util::Time>(
2061 &css::sdbc::XRow::getTime, columnIndex);
2064 //virtual
2065 DateTime SAL_CALL CachedContentResultSet
2066 ::getTimestamp( sal_Int32 columnIndex )
2067 throw( SQLException,
2068 RuntimeException, std::exception )
2070 return rowOriginGet<css::util::DateTime>(
2071 &css::sdbc::XRow::getTimestamp, columnIndex);
2074 //virtual
2075 Reference< com::sun::star::io::XInputStream >
2076 SAL_CALL CachedContentResultSet
2077 ::getBinaryStream( sal_Int32 columnIndex )
2078 throw( SQLException,
2079 RuntimeException, std::exception )
2081 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
2082 &css::sdbc::XRow::getBinaryStream, columnIndex);
2085 //virtual
2086 Reference< com::sun::star::io::XInputStream >
2087 SAL_CALL CachedContentResultSet
2088 ::getCharacterStream( sal_Int32 columnIndex )
2089 throw( SQLException,
2090 RuntimeException, std::exception )
2092 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
2093 &css::sdbc::XRow::getCharacterStream, columnIndex);
2096 //virtual
2097 Any SAL_CALL CachedContentResultSet
2098 ::getObject( sal_Int32 columnIndex,
2099 const Reference<
2100 com::sun::star::container::XNameAccess >& typeMap )
2101 throw( SQLException,
2102 RuntimeException, std::exception )
2104 //if you change this function please pay attention to
2105 //function template rowOriginGet, where this is similar implemented
2107 ReacquireableGuard aGuard( m_aMutex );
2108 sal_Int32 nRow = m_nRow;
2109 sal_Int32 nFetchSize = m_nFetchSize;
2110 sal_Int32 nFetchDirection = m_nFetchDirection;
2111 if( !m_aCache.hasRow( nRow ) )
2113 if( !m_aCache.hasCausedException( nRow ) )
2115 if( !m_xFetchProvider.is() )
2117 OSL_FAIL( "broadcaster was disposed already" );
2118 return Any();
2120 aGuard.clear();
2122 impl_fetchData( nRow, nFetchSize, nFetchDirection );
2124 aGuard.reacquire();
2125 if( !m_aCache.hasRow( nRow ) )
2127 m_bLastReadWasFromCache = false;
2128 aGuard.clear();
2129 applyPositionToOrigin( nRow );
2130 impl_init_xRowOrigin();
2131 return m_xRowOrigin->getObject( columnIndex, typeMap );
2134 //@todo: pay attention to typeMap
2135 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2136 Any aRet;
2137 m_bLastReadWasFromCache = true;
2138 m_bLastCachedReadWasNull = !( rValue >>= aRet );
2139 return aRet;
2142 //virtual
2143 Reference< XRef > SAL_CALL CachedContentResultSet
2144 ::getRef( sal_Int32 columnIndex )
2145 throw( SQLException,
2146 RuntimeException, std::exception )
2148 return rowOriginGet< css::uno::Reference<css::sdbc::XRef> >(
2149 &css::sdbc::XRow::getRef, columnIndex);
2152 //virtual
2153 Reference< XBlob > SAL_CALL CachedContentResultSet
2154 ::getBlob( sal_Int32 columnIndex )
2155 throw( SQLException,
2156 RuntimeException, std::exception )
2158 return rowOriginGet< css::uno::Reference<css::sdbc::XBlob> >(
2159 &css::sdbc::XRow::getBlob, columnIndex);
2162 //virtual
2163 Reference< XClob > SAL_CALL CachedContentResultSet
2164 ::getClob( sal_Int32 columnIndex )
2165 throw( SQLException,
2166 RuntimeException, std::exception )
2168 return rowOriginGet< css::uno::Reference<css::sdbc::XClob> >(
2169 &css::sdbc::XRow::getClob, columnIndex);
2172 //virtual
2173 Reference< XArray > SAL_CALL CachedContentResultSet
2174 ::getArray( sal_Int32 columnIndex )
2175 throw( SQLException,
2176 RuntimeException, std::exception )
2178 return rowOriginGet< css::uno::Reference<css::sdbc::XArray> >(
2179 &css::sdbc::XRow::getArray, columnIndex);
2183 // Type Converter Support
2186 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2188 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2190 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2192 m_bTriedToGetTypeConverter = true;
2193 m_xTypeConverter = Reference< XTypeConverter >( Converter::create(m_xContext) );
2195 OSL_ENSURE( m_xTypeConverter.is(),
2196 "PropertyValueSet::getTypeConverter() - "
2197 "Service 'com.sun.star.script.Converter' n/a!" );
2199 return m_xTypeConverter;
2204 // class CachedContentResultSetFactory
2208 CachedContentResultSetFactory::CachedContentResultSetFactory(
2209 const Reference< XComponentContext > & rxContext )
2211 m_xContext = rxContext;
2214 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2219 // CachedContentResultSetFactory XInterface methods.
2220 void SAL_CALL CachedContentResultSetFactory::acquire()
2221 throw()
2223 OWeakObject::acquire();
2226 void SAL_CALL CachedContentResultSetFactory::release()
2227 throw()
2229 OWeakObject::release();
2232 css::uno::Any SAL_CALL CachedContentResultSetFactory::queryInterface( const css::uno::Type & rType )
2233 throw( css::uno::RuntimeException, std::exception )
2235 css::uno::Any aRet = cppu::queryInterface( rType,
2236 (static_cast< XTypeProvider* >(this)),
2237 (static_cast< XServiceInfo* >(this)),
2238 (static_cast< XCachedContentResultSetFactory* >(this))
2240 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
2243 // CachedContentResultSetFactory XTypeProvider methods.
2246 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2247 XTypeProvider,
2248 XServiceInfo,
2249 XCachedContentResultSetFactory );
2252 // CachedContentResultSetFactory XServiceInfo methods.
2255 XSERVICEINFO_IMPL_1_CTX( CachedContentResultSetFactory,
2256 OUString( "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2257 CACHED_CONTENT_RESULTSET_FACTORY_NAME );
2260 // Service factory implementation.
2263 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2266 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2269 //virtual
2270 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2271 ::createCachedContentResultSet(
2272 const Reference< XResultSet > & xSource,
2273 const Reference< XContentIdentifierMapping > & xMapping )
2274 throw( com::sun::star::uno::RuntimeException, std::exception )
2276 Reference< XResultSet > xRet;
2277 xRet = new CachedContentResultSet( m_xContext, xSource, xMapping );
2278 return xRet;
2281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */