Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultset.cxx
blob7cf70060b213c0212edd25352df832c0ed069100
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cachedcontentresultset.hxx>
22 #include <com/sun/star/sdbc/FetchDirection.hpp>
23 #include <com/sun/star/ucb/FetchError.hpp>
24 #include <com/sun/star/ucb/ResultSetException.hpp>
25 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #include <com/sun/star/script/Converter.hpp>
27 #include <com/sun/star/sdbc/ResultSetType.hpp>
28 #include <rtl/ustring.hxx>
29 #include <osl/diagnose.h>
30 #include <comphelper/processfactory.hxx>
32 using namespace com::sun::star::beans;
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::script;
35 using namespace com::sun::star::sdbc;
36 using namespace com::sun::star::ucb;
37 using namespace com::sun::star::uno;
38 using namespace com::sun::star::util;
39 using namespace cppu;
42 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
43 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
45 //if you change this function template please pay attention to
46 //function getObject, where this is similar implemented
48 template<typename T> T CachedContentResultSet::rowOriginGet(
49 T (SAL_CALL css::sdbc::XRow::* f)(sal_Int32), sal_Int32 columnIndex)
51 impl_EnsureNotDisposed();
52 ReacquireableGuard aGuard( m_aMutex );
53 sal_Int32 nRow = m_nRow;
54 sal_Int32 nFetchSize = m_nFetchSize;
55 sal_Int32 nFetchDirection = m_nFetchDirection;
56 if( !m_aCache.hasRow( nRow ) )
58 if( !m_aCache.hasCausedException( nRow ) )
60 if( !m_xFetchProvider.is() )
62 OSL_FAIL( "broadcaster was disposed already" );
63 throw SQLException();
65 aGuard.clear();
66 if( impl_isForwardOnly() )
67 applyPositionToOrigin( nRow );
69 impl_fetchData( nRow, nFetchSize, nFetchDirection );
71 aGuard.reacquire();
72 if( !m_aCache.hasRow( nRow ) )
74 m_bLastReadWasFromCache = false;
75 aGuard.clear();
76 applyPositionToOrigin( nRow );
77 impl_init_xRowOrigin();
78 return (m_xRowOrigin.get()->*f)( columnIndex );
81 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
82 T aRet = T();
83 m_bLastReadWasFromCache = true;
84 m_bLastCachedReadWasNull = !( rValue >>= aRet );
85 /* Last chance. Try type converter service... */
86 if ( m_bLastCachedReadWasNull && rValue.hasValue() )
88 Reference< XTypeConverter > xConverter = getTypeConverter();
89 if ( xConverter.is() )
91 try
93 Any aConvAny = xConverter->convertTo(
94 rValue,
95 getCppuType( static_cast<
96 const T * >( 0 ) ) );
97 m_bLastCachedReadWasNull = !( aConvAny >>= aRet );
99 catch (const IllegalArgumentException&)
102 catch (const CannotConvertException&)
107 return aRet;
112 // CCRS_Cache methoeds.
116 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
117 const Reference< XContentIdentifierMapping > & xMapping )
118 : m_pResult( NULL )
119 , m_xContentIdentifierMapping( xMapping )
120 , m_pMappedReminder( NULL )
124 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
126 delete m_pResult;
129 void SAL_CALL CachedContentResultSet::CCRS_Cache
130 ::clear()
132 if( m_pResult )
134 delete m_pResult;
135 m_pResult = NULL;
137 clearMappedReminder();
140 void SAL_CALL CachedContentResultSet::CCRS_Cache
141 ::loadData( const FetchResult& rResult )
143 clear();
144 m_pResult = new FetchResult( rResult );
147 bool SAL_CALL CachedContentResultSet::CCRS_Cache
148 ::hasRow( sal_Int32 row )
150 if( !m_pResult )
151 return false;
152 long nStart = m_pResult->StartIndex;
153 long 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 SAL_CALL CachedContentResultSet::CCRS_Cache
163 ::getMaxRow()
165 if( !m_pResult )
166 return 0;
167 long nEnd = m_pResult->StartIndex;
168 if( m_pResult->Orientation )
169 return nEnd += m_pResult->Rows.getLength() - 1;
170 else
171 return nEnd;
174 bool SAL_CALL CachedContentResultSet::CCRS_Cache
175 ::hasKnownLast()
177 if( !m_pResult )
178 return false;
180 if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
181 && m_pResult->Orientation
182 && m_pResult->Rows.getLength() )
183 return true;
185 return false;
188 bool SAL_CALL CachedContentResultSet::CCRS_Cache
189 ::hasCausedException( sal_Int32 nRow )
191 if( !m_pResult )
192 return false;
193 if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
194 return false;
196 long nEnd = m_pResult->StartIndex;
197 if( m_pResult->Orientation )
198 nEnd += m_pResult->Rows.getLength();
200 return nRow == nEnd+1;
203 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
204 ::getRowAny( sal_Int32 nRow )
205 throw( SQLException,
206 RuntimeException )
208 if( !nRow )
209 throw SQLException();
210 if( !m_pResult )
211 throw SQLException();
212 if( !hasRow( nRow ) )
213 throw SQLException();
215 long nDiff = nRow - m_pResult->StartIndex;
216 if( nDiff < 0 )
217 nDiff *= -1;
219 return (m_pResult->Rows)[nDiff];
222 void SAL_CALL CachedContentResultSet::CCRS_Cache
223 ::remindMapped( sal_Int32 nRow )
225 //remind that this row was mapped
226 if( !m_pResult )
227 return;
228 long nDiff = nRow - m_pResult->StartIndex;
229 if( nDiff < 0 )
230 nDiff *= -1;
231 Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
232 if( nDiff < pMappedReminder->getLength() )
233 (*pMappedReminder)[nDiff] = sal_True;
236 bool SAL_CALL CachedContentResultSet::CCRS_Cache
237 ::isRowMapped( sal_Int32 nRow )
239 if( !m_pMappedReminder || !m_pResult )
240 return false;
241 long nDiff = nRow - m_pResult->StartIndex;
242 if( nDiff < 0 )
243 nDiff *= -1;
244 if( nDiff < m_pMappedReminder->getLength() )
245 return (*m_pMappedReminder)[nDiff];
246 return false;
249 void SAL_CALL CachedContentResultSet::CCRS_Cache
250 ::clearMappedReminder()
252 delete m_pMappedReminder;
253 m_pMappedReminder = NULL;
256 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
257 ::getMappedReminder()
259 if( !m_pMappedReminder )
261 sal_Int32 nCount = m_pResult->Rows.getLength();
262 m_pMappedReminder = new Sequence< sal_Bool >( nCount );
263 for( ;nCount; nCount-- )
264 (*m_pMappedReminder)[nCount] = sal_False;
266 return m_pMappedReminder;
269 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
270 ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
271 throw( SQLException,
272 RuntimeException )
274 if( !nColumnIndex )
275 throw SQLException();
276 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
278 Any& rRow = getRowAny( nRow );
279 Sequence< Any > aValue;
280 rRow >>= aValue;
281 if( m_xContentIdentifierMapping->mapRow( aValue ) )
283 rRow <<= aValue;
284 remindMapped( nRow );
286 else
287 m_xContentIdentifierMapping.clear();
289 const Sequence< Any >& rRow =
290 (* reinterpret_cast< const Sequence< Any > * >
291 (getRowAny( nRow ).getValue() ));
293 if( nColumnIndex > rRow.getLength() )
294 throw SQLException();
295 return rRow[nColumnIndex-1];
298 const OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
299 ::getContentIdentifierString( sal_Int32 nRow )
300 throw( com::sun::star::uno::RuntimeException )
304 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
306 Any& rRow = getRowAny( nRow );
307 OUString aValue;
308 rRow >>= aValue;
309 rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
310 remindMapped( nRow );
312 return (* reinterpret_cast< const OUString * >
313 (getRowAny( nRow ).getValue() ));
315 catch(const SQLException&)
317 throw RuntimeException();
321 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
322 ::getContentIdentifier( sal_Int32 nRow )
323 throw( com::sun::star::uno::RuntimeException )
327 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
329 Any& rRow = getRowAny( nRow );
330 Reference< XContentIdentifier > aValue;
331 rRow >>= aValue;
332 rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
333 remindMapped( nRow );
335 return (* reinterpret_cast< const Reference< XContentIdentifier > * >
336 (getRowAny( nRow ).getValue() ));
338 catch(const SQLException&)
340 throw RuntimeException();
344 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
345 ::getContent( sal_Int32 nRow )
346 throw( com::sun::star::uno::RuntimeException )
350 if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
352 Any& rRow = getRowAny( nRow );
353 Reference< XContent > aValue;
354 rRow >>= aValue;
355 rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
356 remindMapped( nRow );
358 return (* reinterpret_cast< const Reference< XContent > * >
359 (getRowAny( nRow ).getValue() ));
361 catch (const SQLException&)
363 throw RuntimeException();
369 // class CCRS_PropertySetInfo
373 class CCRS_PropertySetInfo :
374 public cppu::OWeakObject,
375 public com::sun::star::lang::XTypeProvider,
376 public com::sun::star::beans::XPropertySetInfo
378 friend class CachedContentResultSet;
380 //my Properties
381 Sequence< com::sun::star::beans::Property >*
382 m_pProperties;
384 //some helping variables ( names for my special properties )
385 static OUString m_aPropertyNameForCount;
386 static OUString m_aPropertyNameForFinalCount;
387 static OUString m_aPropertyNameForFetchSize;
388 static OUString m_aPropertyNameForFetchDirection;
390 long m_nFetchSizePropertyHandle;
391 long m_nFetchDirectionPropertyHandle;
393 private:
394 sal_Int32 SAL_CALL
395 impl_getRemainedHandle() const;
397 bool SAL_CALL
398 impl_queryProperty(
399 const OUString& rName
400 , com::sun::star::beans::Property& rProp ) const;
401 sal_Int32 SAL_CALL
402 impl_getPos( const OUString& rName ) const;
404 static bool SAL_CALL
405 impl_isMyPropertyName( const OUString& rName );
407 public:
408 CCRS_PropertySetInfo( Reference<
409 XPropertySetInfo > xPropertySetInfoOrigin );
411 virtual ~CCRS_PropertySetInfo();
413 // XInterface
414 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType )
415 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
416 virtual void SAL_CALL acquire()
417 throw() SAL_OVERRIDE;
418 virtual void SAL_CALL release()
419 throw() SAL_OVERRIDE;
421 // XTypeProvider
422 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId()
423 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
424 virtual css::uno::Sequence< com::sun::star::uno::Type > SAL_CALL getTypes()
425 throw( css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
427 // XPropertySetInfo
428 virtual Sequence< com::sun::star::beans::Property > SAL_CALL
429 getProperties()
430 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
432 virtual com::sun::star::beans::Property SAL_CALL
433 getPropertyByName( const OUString& aName )
434 throw( com::sun::star::beans::UnknownPropertyException, RuntimeException, std::exception ) SAL_OVERRIDE;
436 virtual sal_Bool SAL_CALL
437 hasPropertyByName( const OUString& Name )
438 throw( RuntimeException, std::exception ) SAL_OVERRIDE;
441 OUString CCRS_PropertySetInfo::m_aPropertyNameForCount( "RowCount" );
442 OUString CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( "IsRowCountFinal" );
443 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( "FetchSize" );
444 OUString CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( "FetchDirection" );
446 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
447 Reference< XPropertySetInfo > xInfo )
448 : m_pProperties( NULL )
449 , m_nFetchSizePropertyHandle( -1 )
450 , m_nFetchDirectionPropertyHandle( -1 )
452 //initialize list of properties:
454 // it is required, that the received xInfo contains the two
455 // properties with names 'm_aPropertyNameForCount' and
456 // 'm_aPropertyNameForFinalCount'
458 if( xInfo.is() )
460 Sequence<Property> aProps = xInfo->getProperties();
461 m_pProperties = new Sequence<Property> ( aProps );
463 else
465 OSL_FAIL( "The received XPropertySetInfo doesn't contain required properties" );
466 m_pProperties = new Sequence<Property>;
469 //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
470 sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
471 sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
472 sal_Int32 nDeleted = 0;
473 if( nFetchSize != -1 )
474 nDeleted++;
475 if( nFetchDirection != -1 )
476 nDeleted++;
478 Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
479 sal_Int32 nOrigProps = pOrigProps->getLength();
481 m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
482 for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
484 if( n == nFetchSize || n == nFetchDirection )
485 m--;
486 else
487 (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
490 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
491 rMyProp.Name = m_aPropertyNameForFetchSize;
492 rMyProp.Type = cppu::UnoType<sal_Int32>::get();
493 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
495 if( nFetchSize != -1 )
496 m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
497 else
498 m_nFetchSizePropertyHandle = impl_getRemainedHandle();
500 rMyProp.Handle = m_nFetchSizePropertyHandle;
504 Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
505 rMyProp.Name = m_aPropertyNameForFetchDirection;
506 rMyProp.Type = cppu::UnoType<sal_Bool>::get();
507 rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
509 if( nFetchDirection != -1 )
510 m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
511 else
512 m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
514 m_nFetchDirectionPropertyHandle = rMyProp.Handle;
516 delete pOrigProps;
519 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
521 delete m_pProperties;
525 // XInterface methods.
527 void SAL_CALL CCRS_PropertySetInfo::acquire()
528 throw()
530 OWeakObject::acquire();
533 void SAL_CALL CCRS_PropertySetInfo::release()
534 throw()
536 OWeakObject::release();
539 css::uno::Any SAL_CALL CCRS_PropertySetInfo::queryInterface( const css::uno::Type & rType )
540 throw( css::uno::RuntimeException, std::exception )
542 css::uno::Any aRet = cppu::queryInterface( rType,
543 (static_cast< XTypeProvider* >(this)),
544 (static_cast< XPropertySetInfo* >(this))
546 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
549 // XTypeProvider methods.
551 //list all interfaces exclusive baseclasses
552 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
553 , XTypeProvider
554 , XPropertySetInfo
557 // XPropertySetInfo methods.
559 //virtual
560 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
561 ::getProperties() throw( RuntimeException, std::exception )
563 return *m_pProperties;
566 //virtual
567 Property SAL_CALL CCRS_PropertySetInfo
568 ::getPropertyByName( const OUString& aName )
569 throw( UnknownPropertyException, RuntimeException, std::exception )
571 if ( aName.isEmpty() )
572 throw UnknownPropertyException();
574 Property aProp;
575 if ( impl_queryProperty( aName, aProp ) )
576 return aProp;
578 throw UnknownPropertyException();
581 //virtual
582 sal_Bool SAL_CALL CCRS_PropertySetInfo
583 ::hasPropertyByName( const OUString& Name )
584 throw( RuntimeException, std::exception )
586 return ( impl_getPos( Name ) != -1 );
590 // impl_ methods.
593 sal_Int32 SAL_CALL CCRS_PropertySetInfo
594 ::impl_getPos( const OUString& rName ) const
596 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
598 const Property& rMyProp = (*m_pProperties)[nN];
599 if( rMyProp.Name == rName )
600 return nN;
602 return -1;
605 bool SAL_CALL CCRS_PropertySetInfo
606 ::impl_queryProperty( const OUString& rName, Property& rProp ) const
608 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
610 const Property& rMyProp = (*m_pProperties)[nN];
611 if( rMyProp.Name == rName )
613 rProp.Name = rMyProp.Name;
614 rProp.Handle = rMyProp.Handle;
615 rProp.Type = rMyProp.Type;
616 rProp.Attributes = rMyProp.Attributes;
618 return true;
621 return false;
624 //static
625 bool SAL_CALL CCRS_PropertySetInfo
626 ::impl_isMyPropertyName( const OUString& rPropertyName )
628 return ( rPropertyName == m_aPropertyNameForCount
629 || rPropertyName == m_aPropertyNameForFinalCount
630 || rPropertyName == m_aPropertyNameForFetchSize
631 || rPropertyName == m_aPropertyNameForFetchDirection );
634 sal_Int32 SAL_CALL CCRS_PropertySetInfo
635 ::impl_getRemainedHandle( ) const
637 sal_Int32 nHandle = 1;
639 if( !m_pProperties )
641 OSL_FAIL( "Properties not initialized yet" );
642 return nHandle;
644 bool bFound = true;
645 while( bFound )
647 bFound = false;
648 for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
650 if( nHandle == (*m_pProperties)[nN].Handle )
652 bFound = true;
653 nHandle++;
654 break;
658 return nHandle;
663 // class CachedContentResultSet
667 CachedContentResultSet::CachedContentResultSet(
668 const Reference< XComponentContext > & rxContext
669 , const Reference< XResultSet > & xOrigin
670 , const Reference< XContentIdentifierMapping > &
671 xContentIdentifierMapping )
672 : ContentResultSetWrapper( xOrigin )
674 , m_xContext( rxContext )
675 , m_xFetchProvider( NULL )
676 , m_xFetchProviderForContentAccess( NULL )
678 , m_xMyPropertySetInfo( NULL )
679 , m_pMyPropSetInfo( NULL )
681 , m_xContentIdentifierMapping( xContentIdentifierMapping )
682 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
683 , m_bAfterLast( false )
684 , m_nLastAppliedPos( 0 )
685 , m_bAfterLastApplied( false )
686 , m_nKnownCount( 0 )
687 , m_bFinalCount( false )
688 , m_nFetchSize(
689 COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
690 , m_nFetchDirection(
691 COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
693 , m_bLastReadWasFromCache( false )
694 , m_bLastCachedReadWasNull( true )
695 , m_aCache( m_xContentIdentifierMapping )
696 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
697 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
698 , m_aCacheContent( m_xContentIdentifierMapping )
699 , m_bTriedToGetTypeConverter( false )
700 , m_xTypeConverter( NULL )
702 m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
703 OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
705 m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
706 OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
708 impl_init();
711 CachedContentResultSet::~CachedContentResultSet()
713 impl_deinit();
714 //do not delete m_pMyPropSetInfo, cause it is hold via reference
718 // impl_ methods.
721 bool SAL_CALL CachedContentResultSet
722 ::applyPositionToOrigin( sal_Int32 nRow )
723 throw( SQLException,
724 RuntimeException )
726 impl_EnsureNotDisposed();
729 @returns
730 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
731 the result set.
734 ReacquireableGuard aGuard( m_aMutex );
735 OSL_ENSURE( nRow >= 0, "only positive values supported" );
736 if( !m_xResultSetOrigin.is() )
738 OSL_FAIL( "broadcaster was disposed already" );
739 return false;
741 // OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
743 sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
744 bool bAfterLastApplied = m_bAfterLastApplied;
745 bool bAfterLast = m_bAfterLast;
746 sal_Int32 nForwardOnly = m_nForwardOnly;
748 aGuard.clear();
750 if( bAfterLastApplied || nLastAppliedPos != nRow )
752 if( nForwardOnly == 1 )
754 if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
755 throw SQLException();
757 sal_Int32 nN = nRow - nLastAppliedPos;
758 sal_Int32 nM;
759 for( nM = 0; nN--; nM++ )
761 if( !m_xResultSetOrigin->next() )
762 break;
765 aGuard.reacquire();
766 m_nLastAppliedPos += nM;
767 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
768 return nRow == m_nLastAppliedPos;
771 if( !nRow ) //absolute( 0 ) will throw exception
773 m_xResultSetOrigin->beforeFirst();
775 aGuard.reacquire();
776 m_nLastAppliedPos = 0;
777 m_bAfterLastApplied = false;
778 return false;
782 //move absolute, if !nLastAppliedPos
783 //because move relative would throw exception
784 if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
786 bool bValid = m_xResultSetOrigin->absolute( nRow );
788 aGuard.reacquire();
789 m_nLastAppliedPos = nRow;
790 m_bAfterLastApplied = !bValid;
791 return bValid;
793 else
795 bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
797 aGuard.reacquire();
798 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
799 m_bAfterLastApplied = !bValid;
800 return bValid;
803 catch (const SQLException&)
805 if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
807 sal_Int32 nN = nRow - nLastAppliedPos;
808 sal_Int32 nM;
809 for( nM = 0; nN--; nM++ )
811 if( !m_xResultSetOrigin->next() )
812 break;
815 aGuard.reacquire();
816 m_nLastAppliedPos += nM;
817 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
819 else
820 throw;
823 return nRow == m_nLastAppliedPos;
825 return true;
830 //define for fetching data
834 #define FETCH_XXX( aCache, fetchInterface, fetchMethod ) \
835 bool bDirection = !!( \
836 nFetchDirection != FetchDirection::REVERSE ); \
837 FetchResult aResult = \
838 fetchInterface->fetchMethod( nRow, nFetchSize, bDirection ); \
839 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex ); \
840 aCache.loadData( aResult ); \
841 sal_Int32 nMax = aCache.getMaxRow(); \
842 sal_Int32 nCurCount = m_nKnownCount; \
843 bool bIsFinalCount = aCache.hasKnownLast(); \
844 bool bCurIsFinalCount = m_bFinalCount; \
845 aGuard2.clear(); \
846 if( nMax > nCurCount ) \
847 impl_changeRowCount( nCurCount, nMax ); \
848 if( bIsFinalCount && !bCurIsFinalCount ) \
849 impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
851 void SAL_CALL CachedContentResultSet
852 ::impl_fetchData( sal_Int32 nRow
853 , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
854 throw( com::sun::star::uno::RuntimeException )
856 FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
859 void SAL_CALL CachedContentResultSet
860 ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
862 OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
863 if( nNew <= nOld )
864 return;
866 //create PropertyChangeEvent and set value
867 PropertyChangeEvent aEvt;
869 osl::Guard< osl::Mutex > aGuard( m_aMutex );
870 aEvt.Source = static_cast< XPropertySet * >( this );
871 aEvt.Further = sal_False;
872 aEvt.OldValue <<= nOld;
873 aEvt.NewValue <<= nNew;
875 m_nKnownCount = nNew;
878 //send PropertyChangeEvent to listeners
879 impl_notifyPropertyChangeListeners( aEvt );
882 void SAL_CALL CachedContentResultSet
883 ::impl_changeIsRowCountFinal( bool bOld, bool bNew )
885 OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
886 if( ! (!bOld && bNew ) )
887 return;
889 //create PropertyChangeEvent and set value
890 PropertyChangeEvent aEvt;
892 osl::Guard< osl::Mutex > aGuard( m_aMutex );
893 aEvt.Source = static_cast< XPropertySet * >( this );
894 aEvt.Further = sal_False;
895 aEvt.OldValue <<= bOld;
896 aEvt.NewValue <<= bNew;
898 m_bFinalCount = bNew;
901 //send PropertyChangeEvent to listeners
902 impl_notifyPropertyChangeListeners( aEvt );
905 bool SAL_CALL CachedContentResultSet
906 ::impl_isKnownValidPosition( sal_Int32 nRow )
908 return m_nKnownCount && nRow
909 && nRow <= m_nKnownCount;
912 bool SAL_CALL CachedContentResultSet
913 ::impl_isKnownInvalidPosition( sal_Int32 nRow )
915 if( !nRow )
916 return true;
917 if( !m_bFinalCount )
918 return false;
919 return nRow > m_nKnownCount;
923 //virtual
924 void SAL_CALL CachedContentResultSet
925 ::impl_initPropertySetInfo()
927 ContentResultSetWrapper::impl_initPropertySetInfo();
929 osl::Guard< osl::Mutex > aGuard( m_aMutex );
930 if( m_pMyPropSetInfo )
931 return;
932 m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
933 m_xMyPropertySetInfo = m_pMyPropSetInfo;
934 m_xPropertySetInfo = m_xMyPropertySetInfo;
938 // XInterface methods.
939 void SAL_CALL CachedContentResultSet::acquire()
940 throw()
942 OWeakObject::acquire();
945 void SAL_CALL CachedContentResultSet::release()
946 throw()
948 OWeakObject::release();
951 Any SAL_CALL CachedContentResultSet
952 ::queryInterface( const Type& rType )
953 throw ( RuntimeException, std::exception )
955 //list all interfaces inclusive baseclasses of interfaces
957 Any aRet = ContentResultSetWrapper::queryInterface( rType );
958 if( aRet.hasValue() )
959 return aRet;
961 aRet = cppu::queryInterface( rType,
962 static_cast< XTypeProvider* >( this ),
963 static_cast< XServiceInfo* >( this ) );
965 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
969 // XTypeProvider methods.
971 //list all interfaces exclusive baseclasses
972 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
973 , XTypeProvider
974 , XServiceInfo
975 , XComponent
976 , XCloseable
977 , XResultSetMetaDataSupplier
978 , XPropertySet
980 , XPropertyChangeListener
981 , XVetoableChangeListener
983 , XContentAccess
985 , XResultSet
986 , XRow );
989 // XServiceInfo methods.
992 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
993 OUString(
994 "com.sun.star.comp.ucb.CachedContentResultSet" ),
995 OUString(
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 if( !m_aCache##XXX.hasCausedException( nRow ) ) \
1288 if( !m_xFetchProviderForContentAccess.is() ) \
1290 OSL_FAIL( "broadcaster was disposed already" );\
1291 throw RuntimeException(); \
1293 aGuard.clear(); \
1294 if( impl_isForwardOnly() ) \
1295 applyPositionToOrigin( nRow ); \
1297 FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1299 aGuard.reacquire(); \
1300 if( !m_aCache##XXX.hasRow( nRow ) ) \
1302 aGuard.clear(); \
1303 applyPositionToOrigin( nRow ); \
1304 TYPE aRet = ContentResultSetWrapper::queryXXX(); \
1305 if( m_xContentIdentifierMapping.is() ) \
1306 return m_xContentIdentifierMapping->map##XXX( aRet );\
1307 return aRet; \
1310 return m_aCache##XXX.get##XXX( nRow );
1313 // virtual
1314 OUString SAL_CALL CachedContentResultSet
1315 ::queryContentIdentifierString()
1316 throw( RuntimeException, std::exception )
1318 XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1322 // virtual
1323 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1324 ::queryContentIdentifier()
1325 throw( RuntimeException, std::exception )
1327 XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1331 // virtual
1332 Reference< XContent > SAL_CALL CachedContentResultSet
1333 ::queryContent()
1334 throw( RuntimeException, std::exception )
1336 XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1340 // XResultSet methods. ( inherited )
1342 //virtual
1344 sal_Bool SAL_CALL CachedContentResultSet
1345 ::next()
1346 throw( SQLException,
1347 RuntimeException, std::exception )
1349 impl_EnsureNotDisposed();
1351 ReacquireableGuard aGuard( m_aMutex );
1352 //after last
1353 if( m_bAfterLast )
1354 return sal_False;
1355 //last
1356 aGuard.clear();
1357 if( isLast() )
1359 aGuard.reacquire();
1360 m_nRow++;
1361 m_bAfterLast = true;
1362 return sal_False;
1364 aGuard.reacquire();
1365 //known valid position
1366 if( impl_isKnownValidPosition( m_nRow + 1 ) )
1368 m_nRow++;
1369 return sal_True;
1372 //unknown position
1373 sal_Int32 nRow = m_nRow;
1374 aGuard.clear();
1376 bool bValid = applyPositionToOrigin( nRow + 1 );
1378 aGuard.reacquire();
1379 m_nRow = nRow + 1;
1380 m_bAfterLast = !bValid;
1381 return bValid;
1384 //virtual
1385 sal_Bool SAL_CALL CachedContentResultSet
1386 ::previous()
1387 throw( SQLException,
1388 RuntimeException, std::exception )
1390 impl_EnsureNotDisposed();
1392 if( impl_isForwardOnly() )
1393 throw SQLException();
1395 ReacquireableGuard aGuard( m_aMutex );
1396 //before first ?:
1397 if( !m_bAfterLast && !m_nRow )
1398 return sal_False;
1399 //first ?:
1400 if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1402 m_nRow--;
1403 m_bAfterLast = false;
1404 return sal_False;
1406 //known valid position ?:
1407 if( impl_isKnownValidPosition( m_nRow - 1 ) )
1409 m_nRow--;
1410 m_bAfterLast = false;
1411 return sal_True;
1413 //unknown position:
1414 sal_Int32 nRow = m_nRow;
1415 aGuard.clear();
1417 bool bValid = applyPositionToOrigin( nRow - 1 );
1419 aGuard.reacquire();
1420 m_nRow = nRow - 1;
1421 m_bAfterLast = false;
1422 return bValid;
1425 //virtual
1426 sal_Bool SAL_CALL CachedContentResultSet
1427 ::absolute( sal_Int32 row )
1428 throw( SQLException,
1429 RuntimeException, std::exception )
1431 impl_EnsureNotDisposed();
1433 if( !row )
1434 throw SQLException();
1436 if( impl_isForwardOnly() )
1437 throw SQLException();
1439 ReacquireableGuard aGuard( m_aMutex );
1441 if( !m_xResultSetOrigin.is() )
1443 OSL_FAIL( "broadcaster was disposed already" );
1444 return sal_False;
1446 if( row < 0 )
1448 if( m_bFinalCount )
1450 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1451 bool bValid = true;
1452 if( nNewRow <= 0 )
1454 nNewRow = 0;
1455 bValid = false;
1457 m_nRow = nNewRow;
1458 m_bAfterLast = false;
1459 return bValid;
1461 //unknown final count:
1462 aGuard.clear();
1464 // Solaris has problems catching or propagating derived exceptions
1465 // when only the base class is known, so make ResultSetException
1466 // (derived from SQLException) known here:
1467 bool bValid;
1470 bValid = m_xResultSetOrigin->absolute( row );
1472 catch (const ResultSetException&)
1474 throw;
1477 aGuard.reacquire();
1478 if( m_bFinalCount )
1480 sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1481 if( nNewRow < 0 )
1482 nNewRow = 0;
1483 m_nLastAppliedPos = nNewRow;
1484 m_nRow = nNewRow;
1485 m_bAfterLastApplied = m_bAfterLast = false;
1486 return bValid;
1488 aGuard.clear();
1490 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1492 aGuard.reacquire();
1493 m_nLastAppliedPos = nCurRow;
1494 m_nRow = nCurRow;
1495 m_bAfterLast = false;
1496 return nCurRow != 0;
1498 //row > 0:
1499 if( m_bFinalCount )
1501 if( row > m_nKnownCount )
1503 m_nRow = m_nKnownCount + 1;
1504 m_bAfterLast = true;
1505 return sal_False;
1507 m_nRow = row;
1508 m_bAfterLast = false;
1509 return sal_True;
1511 //unknown new position:
1512 aGuard.clear();
1514 bool bValid = m_xResultSetOrigin->absolute( row );
1516 aGuard.reacquire();
1517 if( m_bFinalCount )
1519 sal_Int32 nNewRow = row;
1520 if( nNewRow > m_nKnownCount )
1522 nNewRow = m_nKnownCount + 1;
1523 m_bAfterLastApplied = m_bAfterLast = true;
1525 else
1526 m_bAfterLastApplied = m_bAfterLast = false;
1528 m_nLastAppliedPos = nNewRow;
1529 m_nRow = nNewRow;
1530 return bValid;
1532 aGuard.clear();
1534 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1535 bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1537 aGuard.reacquire();
1538 m_nLastAppliedPos = nCurRow;
1539 m_nRow = nCurRow;
1540 m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1541 return nCurRow && !bIsAfterLast;
1544 //virtual
1545 sal_Bool SAL_CALL CachedContentResultSet
1546 ::relative( sal_Int32 rows )
1547 throw( SQLException,
1548 RuntimeException, std::exception )
1550 impl_EnsureNotDisposed();
1552 if( impl_isForwardOnly() )
1553 throw SQLException();
1555 ReacquireableGuard aGuard( m_aMutex );
1556 if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1557 throw SQLException();
1559 if( !rows )
1560 return sal_True;
1562 sal_Int32 nNewRow = m_nRow + rows;
1563 if( nNewRow < 0 )
1564 nNewRow = 0;
1566 if( impl_isKnownValidPosition( nNewRow ) )
1568 m_nRow = nNewRow;
1569 m_bAfterLast = false;
1570 return sal_True;
1572 else
1574 //known invalid new position:
1575 if( nNewRow == 0 )
1577 m_bAfterLast = false;
1578 m_nRow = 0;
1579 return sal_False;
1581 if( m_bFinalCount && nNewRow > m_nKnownCount )
1583 m_bAfterLast = true;
1584 m_nRow = m_nKnownCount + 1;
1585 return sal_False;
1587 //unknown new position:
1588 aGuard.clear();
1589 bool bValid = applyPositionToOrigin( nNewRow );
1591 aGuard.reacquire();
1592 m_nRow = nNewRow;
1593 m_bAfterLast = !bValid && nNewRow > 0;
1594 return bValid;
1599 //virtual
1600 sal_Bool SAL_CALL CachedContentResultSet
1601 ::first()
1602 throw( SQLException,
1603 RuntimeException, std::exception )
1605 impl_EnsureNotDisposed();
1607 if( impl_isForwardOnly() )
1608 throw SQLException();
1610 ReacquireableGuard aGuard( m_aMutex );
1611 if( impl_isKnownValidPosition( 1 ) )
1613 m_nRow = 1;
1614 m_bAfterLast = false;
1615 return sal_True;
1617 if( impl_isKnownInvalidPosition( 1 ) )
1619 m_nRow = 1;
1620 m_bAfterLast = false;
1621 return sal_False;
1623 //unknown position
1624 aGuard.clear();
1626 bool bValid = applyPositionToOrigin( 1 );
1628 aGuard.reacquire();
1629 m_nRow = 1;
1630 m_bAfterLast = false;
1631 return bValid;
1634 //virtual
1635 sal_Bool SAL_CALL CachedContentResultSet
1636 ::last()
1637 throw( SQLException,
1638 RuntimeException, std::exception )
1640 impl_EnsureNotDisposed();
1642 if( impl_isForwardOnly() )
1643 throw SQLException();
1645 ReacquireableGuard aGuard( m_aMutex );
1646 if( m_bFinalCount )
1648 m_nRow = m_nKnownCount;
1649 m_bAfterLast = false;
1650 return m_nKnownCount != 0;
1652 //unknown position
1653 if( !m_xResultSetOrigin.is() )
1655 OSL_FAIL( "broadcaster was disposed already" );
1656 return sal_False;
1658 aGuard.clear();
1660 bool bValid = m_xResultSetOrigin->last();
1662 aGuard.reacquire();
1663 m_bAfterLastApplied = m_bAfterLast = false;
1664 if( m_bFinalCount )
1666 m_nLastAppliedPos = m_nKnownCount;
1667 m_nRow = m_nKnownCount;
1668 return bValid;
1670 aGuard.clear();
1672 sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1674 aGuard.reacquire();
1675 m_nLastAppliedPos = nCurRow;
1676 m_nRow = nCurRow;
1677 OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1678 m_nKnownCount = nCurRow;
1679 m_bFinalCount = true;
1680 return nCurRow != 0;
1683 //virtual
1684 void SAL_CALL CachedContentResultSet
1685 ::beforeFirst()
1686 throw( SQLException,
1687 RuntimeException, std::exception )
1689 impl_EnsureNotDisposed();
1691 if( impl_isForwardOnly() )
1692 throw SQLException();
1694 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1695 m_nRow = 0;
1696 m_bAfterLast = false;
1699 //virtual
1700 void SAL_CALL CachedContentResultSet
1701 ::afterLast()
1702 throw( SQLException,
1703 RuntimeException, std::exception )
1705 impl_EnsureNotDisposed();
1707 if( impl_isForwardOnly() )
1708 throw SQLException();
1710 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1711 m_nRow = 1;
1712 m_bAfterLast = true;
1715 //virtual
1716 sal_Bool SAL_CALL CachedContentResultSet
1717 ::isAfterLast()
1718 throw( SQLException,
1719 RuntimeException, std::exception )
1721 impl_EnsureNotDisposed();
1723 ReacquireableGuard aGuard( m_aMutex );
1724 if( !m_bAfterLast )
1725 return sal_False;
1726 if( m_nKnownCount )
1727 return m_bAfterLast;
1728 if( m_bFinalCount )
1729 return sal_False;
1731 if( !m_xResultSetOrigin.is() )
1733 OSL_FAIL( "broadcaster was disposed already" );
1734 return sal_False;
1736 aGuard.clear();
1738 //find out whethter the original resultset contains rows or not
1739 m_xResultSetOrigin->afterLast();
1741 aGuard.reacquire();
1742 m_bAfterLastApplied = true;
1743 aGuard.clear();
1745 return m_xResultSetOrigin->isAfterLast();
1748 //virtual
1749 sal_Bool SAL_CALL CachedContentResultSet
1750 ::isBeforeFirst()
1751 throw( SQLException,
1752 RuntimeException, std::exception )
1754 impl_EnsureNotDisposed();
1756 ReacquireableGuard aGuard( m_aMutex );
1757 if( m_bAfterLast )
1758 return sal_False;
1759 if( m_nRow )
1760 return sal_False;
1761 if( m_nKnownCount )
1762 return !m_nRow;
1763 if( m_bFinalCount )
1764 return sal_False;
1766 if( !m_xResultSetOrigin.is() )
1768 OSL_FAIL( "broadcaster was disposed already" );
1769 return sal_False;
1771 aGuard.clear();
1773 //find out whethter the original resultset contains rows or not
1774 m_xResultSetOrigin->beforeFirst();
1776 aGuard.reacquire();
1777 m_bAfterLastApplied = false;
1778 m_nLastAppliedPos = 0;
1779 aGuard.clear();
1781 return m_xResultSetOrigin->isBeforeFirst();
1784 //virtual
1785 sal_Bool SAL_CALL CachedContentResultSet
1786 ::isFirst()
1787 throw( SQLException,
1788 RuntimeException, std::exception )
1790 impl_EnsureNotDisposed();
1792 sal_Int32 nRow = 0;
1793 Reference< XResultSet > xResultSetOrigin;
1796 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1797 if( m_bAfterLast )
1798 return sal_False;
1799 if( m_nRow != 1 )
1800 return sal_False;
1801 if( m_nKnownCount )
1802 return m_nRow == 1;
1803 if( m_bFinalCount )
1804 return sal_False;
1806 nRow = m_nRow;
1807 xResultSetOrigin = m_xResultSetOrigin;
1810 //need to ask origin
1812 if( applyPositionToOrigin( nRow ) )
1813 return xResultSetOrigin->isFirst();
1814 else
1815 return sal_False;
1819 //virtual
1820 sal_Bool SAL_CALL CachedContentResultSet
1821 ::isLast()
1822 throw( SQLException,
1823 RuntimeException, std::exception )
1825 impl_EnsureNotDisposed();
1827 sal_Int32 nRow = 0;
1828 Reference< XResultSet > xResultSetOrigin;
1830 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1831 if( m_bAfterLast )
1832 return sal_False;
1833 if( m_nRow < m_nKnownCount )
1834 return sal_False;
1835 if( m_bFinalCount )
1836 return m_nKnownCount && m_nRow == m_nKnownCount;
1838 nRow = m_nRow;
1839 xResultSetOrigin = m_xResultSetOrigin;
1842 //need to ask origin
1844 if( applyPositionToOrigin( nRow ) )
1845 return xResultSetOrigin->isLast();
1846 else
1847 return sal_False;
1852 //virtual
1853 sal_Int32 SAL_CALL CachedContentResultSet
1854 ::getRow()
1855 throw( SQLException,
1856 RuntimeException, std::exception )
1858 impl_EnsureNotDisposed();
1860 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1861 if( m_bAfterLast )
1862 return 0;
1863 return m_nRow;
1866 //virtual
1867 void SAL_CALL CachedContentResultSet
1868 ::refreshRow()
1869 throw( SQLException,
1870 RuntimeException, std::exception )
1872 impl_EnsureNotDisposed();
1874 //the ContentResultSet is static and will not change
1875 //therefore we don't need to reload anything
1878 //virtual
1879 sal_Bool SAL_CALL CachedContentResultSet
1880 ::rowUpdated()
1881 throw( SQLException,
1882 RuntimeException, std::exception )
1884 impl_EnsureNotDisposed();
1886 //the ContentResultSet is static and will not change
1887 return sal_False;
1889 //virtual
1890 sal_Bool SAL_CALL CachedContentResultSet
1891 ::rowInserted()
1892 throw( SQLException,
1893 RuntimeException, std::exception )
1895 impl_EnsureNotDisposed();
1897 //the ContentResultSet is static and will not change
1898 return sal_False;
1901 //virtual
1902 sal_Bool SAL_CALL CachedContentResultSet
1903 ::rowDeleted()
1904 throw( SQLException,
1905 RuntimeException, std::exception )
1907 impl_EnsureNotDisposed();
1909 //the ContentResultSet is static and will not change
1910 return sal_False;
1913 //virtual
1914 Reference< XInterface > SAL_CALL CachedContentResultSet
1915 ::getStatement()
1916 throw( SQLException,
1917 RuntimeException, std::exception )
1919 impl_EnsureNotDisposed();
1920 //@todo ?return anything
1921 return Reference< XInterface >();
1925 // XRow methods. ( inherited )
1928 //virtual
1929 sal_Bool SAL_CALL CachedContentResultSet
1930 ::wasNull()
1931 throw( SQLException,
1932 RuntimeException, std::exception )
1934 impl_EnsureNotDisposed();
1935 impl_init_xRowOrigin();
1937 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1938 if( m_bLastReadWasFromCache )
1939 return m_bLastCachedReadWasNull;
1940 if( !m_xRowOrigin.is() )
1942 OSL_FAIL( "broadcaster was disposed already" );
1943 return sal_False;
1946 return m_xRowOrigin->wasNull();
1949 //virtual
1950 OUString SAL_CALL CachedContentResultSet
1951 ::getString( sal_Int32 columnIndex )
1952 throw( SQLException,
1953 RuntimeException, std::exception )
1955 return rowOriginGet<OUString>(&css::sdbc::XRow::getString, columnIndex);
1958 //virtual
1959 sal_Bool SAL_CALL CachedContentResultSet
1960 ::getBoolean( sal_Int32 columnIndex )
1961 throw( SQLException,
1962 RuntimeException, std::exception )
1964 return rowOriginGet<sal_Bool>(&css::sdbc::XRow::getBoolean, columnIndex);
1967 //virtual
1968 sal_Int8 SAL_CALL CachedContentResultSet
1969 ::getByte( sal_Int32 columnIndex )
1970 throw( SQLException,
1971 RuntimeException, std::exception )
1973 return rowOriginGet<sal_Int8>(&css::sdbc::XRow::getByte, columnIndex);
1976 //virtual
1977 sal_Int16 SAL_CALL CachedContentResultSet
1978 ::getShort( sal_Int32 columnIndex )
1979 throw( SQLException,
1980 RuntimeException, std::exception )
1982 return rowOriginGet<sal_Int16>(&css::sdbc::XRow::getShort, columnIndex);
1985 //virtual
1986 sal_Int32 SAL_CALL CachedContentResultSet
1987 ::getInt( sal_Int32 columnIndex )
1988 throw( SQLException,
1989 RuntimeException, std::exception )
1991 return rowOriginGet<sal_Int32>(&css::sdbc::XRow::getInt, columnIndex);
1994 //virtual
1995 sal_Int64 SAL_CALL CachedContentResultSet
1996 ::getLong( sal_Int32 columnIndex )
1997 throw( SQLException,
1998 RuntimeException, std::exception )
2000 return rowOriginGet<sal_Int64>(&css::sdbc::XRow::getLong, columnIndex);
2003 //virtual
2004 float SAL_CALL CachedContentResultSet
2005 ::getFloat( sal_Int32 columnIndex )
2006 throw( SQLException,
2007 RuntimeException, std::exception )
2009 return rowOriginGet<float>(&css::sdbc::XRow::getFloat, columnIndex);
2012 //virtual
2013 double SAL_CALL CachedContentResultSet
2014 ::getDouble( sal_Int32 columnIndex )
2015 throw( SQLException,
2016 RuntimeException, std::exception )
2018 return rowOriginGet<double>(&css::sdbc::XRow::getDouble, columnIndex);
2021 //virtual
2022 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
2023 ::getBytes( sal_Int32 columnIndex )
2024 throw( SQLException,
2025 RuntimeException, std::exception )
2027 return rowOriginGet< css::uno::Sequence<sal_Int8> >(
2028 &css::sdbc::XRow::getBytes, columnIndex);
2031 //virtual
2032 Date SAL_CALL CachedContentResultSet
2033 ::getDate( sal_Int32 columnIndex )
2034 throw( SQLException,
2035 RuntimeException, std::exception )
2037 return rowOriginGet<css::util::Date>(
2038 &css::sdbc::XRow::getDate, columnIndex);
2041 //virtual
2042 Time SAL_CALL CachedContentResultSet
2043 ::getTime( sal_Int32 columnIndex )
2044 throw( SQLException,
2045 RuntimeException, std::exception )
2047 return rowOriginGet<css::util::Time>(
2048 &css::sdbc::XRow::getTime, columnIndex);
2051 //virtual
2052 DateTime SAL_CALL CachedContentResultSet
2053 ::getTimestamp( sal_Int32 columnIndex )
2054 throw( SQLException,
2055 RuntimeException, std::exception )
2057 return rowOriginGet<css::util::DateTime>(
2058 &css::sdbc::XRow::getTimestamp, columnIndex);
2061 //virtual
2062 Reference< com::sun::star::io::XInputStream >
2063 SAL_CALL CachedContentResultSet
2064 ::getBinaryStream( sal_Int32 columnIndex )
2065 throw( SQLException,
2066 RuntimeException, std::exception )
2068 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
2069 &css::sdbc::XRow::getBinaryStream, columnIndex);
2072 //virtual
2073 Reference< com::sun::star::io::XInputStream >
2074 SAL_CALL CachedContentResultSet
2075 ::getCharacterStream( sal_Int32 columnIndex )
2076 throw( SQLException,
2077 RuntimeException, std::exception )
2079 return rowOriginGet< css::uno::Reference<css::io::XInputStream> >(
2080 &css::sdbc::XRow::getCharacterStream, columnIndex);
2083 //virtual
2084 Any SAL_CALL CachedContentResultSet
2085 ::getObject( sal_Int32 columnIndex,
2086 const Reference<
2087 com::sun::star::container::XNameAccess >& typeMap )
2088 throw( SQLException,
2089 RuntimeException, std::exception )
2091 //if you change this function please pay attention to
2092 //function template rowOriginGet, where this is similar implemented
2094 ReacquireableGuard aGuard( m_aMutex );
2095 sal_Int32 nRow = m_nRow;
2096 sal_Int32 nFetchSize = m_nFetchSize;
2097 sal_Int32 nFetchDirection = m_nFetchDirection;
2098 if( !m_aCache.hasRow( nRow ) )
2100 if( !m_aCache.hasCausedException( nRow ) )
2102 if( !m_xFetchProvider.is() )
2104 OSL_FAIL( "broadcaster was disposed already" );
2105 return Any();
2107 aGuard.clear();
2109 impl_fetchData( nRow, nFetchSize, nFetchDirection );
2111 aGuard.reacquire();
2112 if( !m_aCache.hasRow( nRow ) )
2114 m_bLastReadWasFromCache = false;
2115 aGuard.clear();
2116 applyPositionToOrigin( nRow );
2117 impl_init_xRowOrigin();
2118 return m_xRowOrigin->getObject( columnIndex, typeMap );
2121 //@todo: pay attention to typeMap
2122 const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2123 Any aRet;
2124 m_bLastReadWasFromCache = true;
2125 m_bLastCachedReadWasNull = !( rValue >>= aRet );
2126 return aRet;
2129 //virtual
2130 Reference< XRef > SAL_CALL CachedContentResultSet
2131 ::getRef( sal_Int32 columnIndex )
2132 throw( SQLException,
2133 RuntimeException, std::exception )
2135 return rowOriginGet< css::uno::Reference<css::sdbc::XRef> >(
2136 &css::sdbc::XRow::getRef, columnIndex);
2139 //virtual
2140 Reference< XBlob > SAL_CALL CachedContentResultSet
2141 ::getBlob( sal_Int32 columnIndex )
2142 throw( SQLException,
2143 RuntimeException, std::exception )
2145 return rowOriginGet< css::uno::Reference<css::sdbc::XBlob> >(
2146 &css::sdbc::XRow::getBlob, columnIndex);
2149 //virtual
2150 Reference< XClob > SAL_CALL CachedContentResultSet
2151 ::getClob( sal_Int32 columnIndex )
2152 throw( SQLException,
2153 RuntimeException, std::exception )
2155 return rowOriginGet< css::uno::Reference<css::sdbc::XClob> >(
2156 &css::sdbc::XRow::getClob, columnIndex);
2159 //virtual
2160 Reference< XArray > SAL_CALL CachedContentResultSet
2161 ::getArray( sal_Int32 columnIndex )
2162 throw( SQLException,
2163 RuntimeException, std::exception )
2165 return rowOriginGet< css::uno::Reference<css::sdbc::XArray> >(
2166 &css::sdbc::XRow::getArray, columnIndex);
2170 // Type Converter Support
2173 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2175 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2177 if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2179 m_bTriedToGetTypeConverter = true;
2180 m_xTypeConverter = Reference< XTypeConverter >( Converter::create(m_xContext) );
2182 OSL_ENSURE( m_xTypeConverter.is(),
2183 "PropertyValueSet::getTypeConverter() - "
2184 "Service 'com.sun.star.script.Converter' n/a!" );
2186 return m_xTypeConverter;
2191 // class CachedContentResultSetFactory
2195 CachedContentResultSetFactory::CachedContentResultSetFactory(
2196 const Reference< XComponentContext > & rxContext )
2198 m_xContext = rxContext;
2201 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2206 // CachedContentResultSetFactory XInterface methods.
2207 void SAL_CALL CachedContentResultSetFactory::acquire()
2208 throw()
2210 OWeakObject::acquire();
2213 void SAL_CALL CachedContentResultSetFactory::release()
2214 throw()
2216 OWeakObject::release();
2219 css::uno::Any SAL_CALL CachedContentResultSetFactory::queryInterface( const css::uno::Type & rType )
2220 throw( css::uno::RuntimeException, std::exception )
2222 css::uno::Any aRet = cppu::queryInterface( rType,
2223 (static_cast< XTypeProvider* >(this)),
2224 (static_cast< XServiceInfo* >(this)),
2225 (static_cast< XCachedContentResultSetFactory* >(this))
2227 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
2230 // CachedContentResultSetFactory XTypeProvider methods.
2233 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2234 XTypeProvider,
2235 XServiceInfo,
2236 XCachedContentResultSetFactory );
2239 // CachedContentResultSetFactory XServiceInfo methods.
2242 XSERVICEINFO_IMPL_1_CTX( CachedContentResultSetFactory,
2243 OUString( "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2244 OUString( CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2247 // Service factory implementation.
2250 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2253 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2256 //virtual
2257 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2258 ::createCachedContentResultSet(
2259 const Reference< XResultSet > & xSource,
2260 const Reference< XContentIdentifierMapping > & xMapping )
2261 throw( com::sun::star::uno::RuntimeException, std::exception )
2263 Reference< XResultSet > xRet;
2264 xRet = new CachedContentResultSet( m_xContext, xSource, xMapping );
2265 return xRet;
2268 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */