xref: /trunk/main/ucb/source/cacher/cachedcontentresultset.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucb.hxx"
30 
31 #include <cachedcontentresultset.hxx>
32 #include <com/sun/star/sdbc/FetchDirection.hpp>
33 #include <com/sun/star/ucb/FetchError.hpp>
34 #include <com/sun/star/ucb/ResultSetException.hpp>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/script/XTypeConverter.hpp>
37 #include <com/sun/star/sdbc/ResultSetType.hpp>
38 #include <rtl/ustring.hxx>
39 #include <osl/diagnose.h>
40 
41 using namespace com::sun::star::beans;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star::script;
44 using namespace com::sun::star::sdbc;
45 using namespace com::sun::star::ucb;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::util;
48 using namespace cppu;
49 using namespace rtl;
50 
51 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
52 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
53 
54 //--------------------------------------------------------------------------
55 //--------------------------------------------------------------------------
56 //define for getXXX methods of interface XRow
57 //--------------------------------------------------------------------------
58 //--------------------------------------------------------------------------
59 
60 //if you change this macro please pay attention to
61 //function ::getObject, where this is similar implemented
62 
63 #define XROW_GETXXX( getXXX, Type )                     \
64 impl_EnsureNotDisposed();                               \
65 ReacquireableGuard aGuard( m_aMutex );                  \
66 sal_Int32 nRow = m_nRow;                                \
67 sal_Int32 nFetchSize = m_nFetchSize;                    \
68 sal_Int32 nFetchDirection = m_nFetchDirection;          \
69 if( !m_aCache.hasRow( nRow ) )                          \
70 {                                                       \
71     if( !m_aCache.hasCausedException( nRow ) )          \
72 {                                                       \
73         if( !m_xFetchProvider.is() )                    \
74         {                                               \
75             OSL_ENSURE( sal_False, "broadcaster was disposed already" );    \
76             throw SQLException();                       \
77         }                                               \
78         aGuard.clear();                                 \
79         if( impl_isForwardOnly() )                      \
80             applyPositionToOrigin( nRow );              \
81                                                         \
82         impl_fetchData( nRow, nFetchSize, nFetchDirection ); \
83     }                                                   \
84     aGuard.reacquire();                                 \
85     if( !m_aCache.hasRow( nRow ) )                      \
86     {                                                   \
87         m_bLastReadWasFromCache = sal_False;            \
88         aGuard.clear();                                 \
89         applyPositionToOrigin( nRow );                  \
90         impl_init_xRowOrigin();                         \
91         return m_xRowOrigin->getXXX( columnIndex );     \
92     }                                                   \
93 }                                                       \
94 const Any& rValue = m_aCache.getAny( nRow, columnIndex );\
95 Type aRet = Type();                                     \
96 m_bLastReadWasFromCache = sal_True;                     \
97 m_bLastCachedReadWasNull = !( rValue >>= aRet );        \
98 /* Last chance. Try type converter service... */        \
99 if ( m_bLastCachedReadWasNull && rValue.hasValue() )    \
100 {                                                       \
101     Reference< XTypeConverter > xConverter              \
102                                 = getTypeConverter();   \
103     if ( xConverter.is() )                              \
104     {                                                   \
105         try                                             \
106         {                                               \
107             Any aConvAny = xConverter->convertTo(       \
108                 rValue,                                 \
109                 getCppuType( static_cast<               \
110                     const Type * >( 0 ) ) );            \
111             m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \
112         }                                               \
113         catch ( IllegalArgumentException )              \
114         {                                               \
115         }                                               \
116         catch ( CannotConvertException )                \
117         {                                               \
118         }                                               \
119     }                                                   \
120 }                                                       \
121 return aRet;
122 
123 //--------------------------------------------------------------------------
124 //--------------------------------------------------------------------------
125 // CCRS_Cache methoeds.
126 //--------------------------------------------------------------------------
127 //--------------------------------------------------------------------------
128 
129 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
130     const Reference< XContentIdentifierMapping > & xMapping )
131     : m_pResult( NULL )
132     , m_xContentIdentifierMapping( xMapping )
133     , m_pMappedReminder( NULL )
134 {
135 }
136 
137 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
138 {
139     delete m_pResult;
140 }
141 
142 void SAL_CALL CachedContentResultSet::CCRS_Cache
143     ::clear()
144 {
145     if( m_pResult )
146     {
147         delete m_pResult;
148         m_pResult = NULL;
149     }
150     clearMappedReminder();
151 }
152 
153 void SAL_CALL CachedContentResultSet::CCRS_Cache
154     ::loadData( const FetchResult& rResult )
155 {
156     clear();
157     m_pResult = new FetchResult( rResult );
158 }
159 
160 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
161     ::hasRow( sal_Int32 row )
162 {
163     if( !m_pResult )
164         return sal_False;
165     long nStart = m_pResult->StartIndex;
166     long nEnd = nStart;
167     if( m_pResult->Orientation )
168         nEnd += m_pResult->Rows.getLength() - 1;
169     else
170         nStart -= m_pResult->Rows.getLength() + 1;
171 
172     return nStart <= row && row <= nEnd;
173 }
174 
175 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
176     ::getMaxRow()
177 {
178     if( !m_pResult )
179         return 0;
180     long nEnd = m_pResult->StartIndex;
181     if( m_pResult->Orientation )
182         return nEnd += m_pResult->Rows.getLength() - 1;
183     else
184         return nEnd;
185 }
186 
187 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
188     ::hasKnownLast()
189 {
190     if( !m_pResult )
191         return sal_False;
192 
193     if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
194         && m_pResult->Orientation
195         && m_pResult->Rows.getLength() )
196         return sal_True;
197 
198     return sal_False;
199 }
200 
201 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
202     ::hasCausedException( sal_Int32 nRow )
203 {
204     if( !m_pResult )
205         return sal_False;
206     if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
207         return sal_False;
208 
209     long nEnd = m_pResult->StartIndex;
210     if( m_pResult->Orientation )
211         nEnd += m_pResult->Rows.getLength();
212 
213     return nRow == nEnd+1;
214 }
215 
216 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
217     ::getRowAny( sal_Int32 nRow )
218     throw( SQLException,
219     RuntimeException )
220 {
221     if( !nRow )
222         throw SQLException();
223     if( !m_pResult )
224         throw SQLException();
225     if( !hasRow( nRow ) )
226         throw SQLException();
227 
228     long nDiff = nRow - m_pResult->StartIndex;
229     if( nDiff < 0 )
230         nDiff *= -1;
231 
232     return (m_pResult->Rows)[nDiff];
233 }
234 
235 void SAL_CALL CachedContentResultSet::CCRS_Cache
236     ::remindMapped( sal_Int32 nRow )
237 {
238     //remind that this row was mapped
239     if( !m_pResult )
240         return;
241     long nDiff = nRow - m_pResult->StartIndex;
242     if( nDiff < 0 )
243         nDiff *= -1;
244     Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
245     if( nDiff < pMappedReminder->getLength() )
246         (*pMappedReminder)[nDiff] = sal_True;
247 }
248 
249 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
250     ::isRowMapped( sal_Int32 nRow )
251 {
252     if( !m_pMappedReminder || !m_pResult )
253         return sal_False;
254     long nDiff = nRow - m_pResult->StartIndex;
255     if( nDiff < 0 )
256         nDiff *= -1;
257     if( nDiff < m_pMappedReminder->getLength() )
258         return (*m_pMappedReminder)[nDiff];
259     return sal_False;
260 }
261 
262 void SAL_CALL CachedContentResultSet::CCRS_Cache
263     ::clearMappedReminder()
264 {
265     delete m_pMappedReminder;
266     m_pMappedReminder = NULL;
267 }
268 
269 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
270     ::getMappedReminder()
271 {
272     if( !m_pMappedReminder )
273     {
274         sal_Int32 nCount = m_pResult->Rows.getLength();
275         m_pMappedReminder = new Sequence< sal_Bool >( nCount );
276         for( ;nCount; nCount-- )
277             (*m_pMappedReminder)[nCount] = sal_False;
278     }
279     return m_pMappedReminder;
280 }
281 
282 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
283     ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
284     throw( SQLException,
285     RuntimeException )
286 {
287     if( !nColumnIndex )
288         throw SQLException();
289     if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
290     {
291         Any& rRow = getRowAny( nRow );
292         Sequence< Any > aValue;
293         rRow >>= aValue;
294         if( m_xContentIdentifierMapping->mapRow( aValue ) )
295         {
296             rRow <<= aValue;
297             remindMapped( nRow );
298         }
299         else
300             m_xContentIdentifierMapping.clear();
301     }
302     const Sequence< Any >& rRow =
303         (* reinterpret_cast< const Sequence< Any > * >
304         (getRowAny( nRow ).getValue() ));
305 
306     if( nColumnIndex > rRow.getLength() )
307         throw SQLException();
308     return rRow[nColumnIndex-1];
309 }
310 
311 const rtl::OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
312     ::getContentIdentifierString( sal_Int32 nRow )
313     throw( com::sun::star::uno::RuntimeException )
314 {
315     try
316     {
317         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
318         {
319             Any& rRow = getRowAny( nRow );
320             rtl::OUString aValue;
321             rRow >>= aValue;
322             rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
323             remindMapped( nRow );
324         }
325         return (* reinterpret_cast< const rtl::OUString * >
326                 (getRowAny( nRow ).getValue() ));
327     }
328     catch( SQLException )
329     {
330         throw RuntimeException();
331     }
332 }
333 
334 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
335     ::getContentIdentifier( sal_Int32 nRow )
336     throw( com::sun::star::uno::RuntimeException )
337 {
338     try
339     {
340         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
341         {
342             Any& rRow = getRowAny( nRow );
343             Reference< XContentIdentifier > aValue;
344             rRow >>= aValue;
345             rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
346             remindMapped( nRow );
347         }
348         return (* reinterpret_cast< const Reference< XContentIdentifier > * >
349                 (getRowAny( nRow ).getValue() ));
350     }
351     catch( SQLException )
352     {
353         throw RuntimeException();
354     }
355 }
356 
357 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
358     ::getContent( sal_Int32 nRow )
359     throw( com::sun::star::uno::RuntimeException )
360 {
361     try
362     {
363         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
364         {
365             Any& rRow = getRowAny( nRow );
366             Reference< XContent > aValue;
367             rRow >>= aValue;
368             rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
369             remindMapped( nRow );
370         }
371         return (* reinterpret_cast< const Reference< XContent > * >
372                 (getRowAny( nRow ).getValue() ));
373     }
374     catch( SQLException )
375     {
376         throw RuntimeException();
377     }
378 }
379 
380 //--------------------------------------------------------------------------
381 //--------------------------------------------------------------------------
382 // class CCRS_PropertySetInfo
383 //--------------------------------------------------------------------------
384 //--------------------------------------------------------------------------
385 
386 class CCRS_PropertySetInfo :
387                 public cppu::OWeakObject,
388                 public com::sun::star::lang::XTypeProvider,
389                 public com::sun::star::beans::XPropertySetInfo
390 {
391     friend class CachedContentResultSet;
392 
393     //my Properties
394     Sequence< com::sun::star::beans::Property >*
395                             m_pProperties;
396 
397     //some helping variables ( names for my special properties )
398     static rtl::OUString    m_aPropertyNameForCount;
399     static rtl::OUString    m_aPropertyNameForFinalCount;
400     static rtl::OUString    m_aPropertyNameForFetchSize;
401     static rtl::OUString    m_aPropertyNameForFetchDirection;
402 
403     long                    m_nFetchSizePropertyHandle;
404     long                    m_nFetchDirectionPropertyHandle;
405 
406 private:
407     sal_Int32 SAL_CALL
408     impl_getRemainedHandle() const;
409 
410     sal_Bool SAL_CALL
411     impl_queryProperty(
412             const rtl::OUString& rName
413             , com::sun::star::beans::Property& rProp ) const;
414     sal_Int32 SAL_CALL
415     impl_getPos( const rtl::OUString& rName ) const;
416 
417     static sal_Bool SAL_CALL
418     impl_isMyPropertyName( const rtl::OUString& rName );
419 
420 public:
421     CCRS_PropertySetInfo(   Reference<
422             XPropertySetInfo > xPropertySetInfoOrigin );
423 
424     virtual ~CCRS_PropertySetInfo();
425 
426     // XInterface
427     XINTERFACE_DECL()
428 
429     // XTypeProvider
430     XTYPEPROVIDER_DECL()
431 
432     // XPropertySetInfo
433     virtual Sequence< com::sun::star::beans::Property > SAL_CALL
434     getProperties()
435         throw( RuntimeException );
436 
437     virtual com::sun::star::beans::Property SAL_CALL
438     getPropertyByName( const rtl::OUString& aName )
439         throw( com::sun::star::beans::UnknownPropertyException, RuntimeException );
440 
441     virtual sal_Bool SAL_CALL
442     hasPropertyByName( const rtl::OUString& Name )
443         throw( RuntimeException );
444 };
445 
446 OUString    CCRS_PropertySetInfo::m_aPropertyNameForCount( OUString::createFromAscii( "RowCount" ) );
447 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( OUString::createFromAscii( "IsRowCountFinal" ) );
448 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) );
449 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) );
450 
451 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
452         Reference< XPropertySetInfo > xInfo )
453         : m_pProperties( NULL )
454         , m_nFetchSizePropertyHandle( -1 )
455         , m_nFetchDirectionPropertyHandle( -1 )
456 {
457     //initialize list of properties:
458 
459     // it is required, that the received xInfo contains the two
460     // properties with names 'm_aPropertyNameForCount' and
461     // 'm_aPropertyNameForFinalCount'
462 
463     if( xInfo.is() )
464     {
465         Sequence<Property> aProps = xInfo->getProperties();
466         m_pProperties = new Sequence<Property> ( aProps );
467     }
468     else
469     {
470         OSL_ENSURE( sal_False, "The received XPropertySetInfo doesn't contain required properties" );
471         m_pProperties = new Sequence<Property>;
472     }
473 
474     //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
475     sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
476     sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
477     sal_Int32 nDeleted = 0;
478     if( nFetchSize != -1 )
479         nDeleted++;
480     if( nFetchDirection != -1 )
481         nDeleted++;
482 
483     Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
484     sal_Int32 nOrigProps = pOrigProps->getLength();
485 
486     m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
487     for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
488     {
489         if( n == nFetchSize || n == nFetchDirection )
490             m--;
491         else
492             (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
493     }
494     {
495         Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
496         rMyProp.Name = m_aPropertyNameForFetchSize;
497         rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) );
498         rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
499 
500         if( nFetchSize != -1 )
501             m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
502         else
503             m_nFetchSizePropertyHandle = impl_getRemainedHandle();
504 
505         rMyProp.Handle = m_nFetchSizePropertyHandle;
506 
507     }
508     {
509         Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
510         rMyProp.Name = m_aPropertyNameForFetchDirection;
511         rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) );
512         rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
513 
514         if( nFetchSize != -1 )
515             m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
516         else
517             m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
518 
519         m_nFetchDirectionPropertyHandle = rMyProp.Handle;
520     }
521     delete pOrigProps;
522 }
523 
524 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
525 {
526     delete m_pProperties;
527 }
528 
529 //--------------------------------------------------------------------------
530 // XInterface methods.
531 //--------------------------------------------------------------------------
532 //list all interfaces inclusive baseclasses of interfaces
533 XINTERFACE_IMPL_2( CCRS_PropertySetInfo
534                   , XTypeProvider
535                   , XPropertySetInfo
536                   );
537 
538 //--------------------------------------------------------------------------
539 // XTypeProvider methods.
540 //--------------------------------------------------------------------------
541 //list all interfaces exclusive baseclasses
542 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
543                     , XTypeProvider
544                     , XPropertySetInfo
545                     );
546 //--------------------------------------------------------------------------
547 // XPropertySetInfo methods.
548 //--------------------------------------------------------------------------
549 //virtual
550 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
551     ::getProperties() throw( RuntimeException )
552 {
553     return *m_pProperties;
554 }
555 
556 //virtual
557 Property SAL_CALL CCRS_PropertySetInfo
558     ::getPropertyByName( const rtl::OUString& aName )
559         throw( UnknownPropertyException, RuntimeException )
560 {
561     if ( !aName.getLength() )
562         throw UnknownPropertyException();
563 
564     Property aProp;
565     if ( impl_queryProperty( aName, aProp ) )
566         return aProp;
567 
568     throw UnknownPropertyException();
569 }
570 
571 //virtual
572 sal_Bool SAL_CALL CCRS_PropertySetInfo
573     ::hasPropertyByName( const rtl::OUString& Name )
574         throw( RuntimeException )
575 {
576     return ( impl_getPos( Name ) != -1 );
577 }
578 
579 //--------------------------------------------------------------------------
580 // impl_ methods.
581 //--------------------------------------------------------------------------
582 
583 sal_Int32 SAL_CALL CCRS_PropertySetInfo
584             ::impl_getPos( const OUString& rName ) const
585 {
586     for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
587     {
588         const Property& rMyProp = (*m_pProperties)[nN];
589         if( rMyProp.Name == rName )
590             return nN;
591     }
592     return -1;
593 }
594 
595 sal_Bool SAL_CALL CCRS_PropertySetInfo
596         ::impl_queryProperty( const OUString& rName, Property& rProp ) const
597 {
598     for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
599     {
600         const Property& rMyProp = (*m_pProperties)[nN];
601         if( rMyProp.Name == rName )
602         {
603             rProp.Name = rMyProp.Name;
604             rProp.Handle = rMyProp.Handle;
605             rProp.Type = rMyProp.Type;
606             rProp.Attributes = rMyProp.Attributes;
607 
608             return sal_True;
609         }
610     }
611     return sal_False;
612 }
613 
614 //static
615 sal_Bool SAL_CALL CCRS_PropertySetInfo
616         ::impl_isMyPropertyName( const OUString& rPropertyName )
617 {
618     return ( rPropertyName == m_aPropertyNameForCount
619     || rPropertyName == m_aPropertyNameForFinalCount
620     || rPropertyName == m_aPropertyNameForFetchSize
621     || rPropertyName == m_aPropertyNameForFetchDirection );
622 }
623 
624 sal_Int32 SAL_CALL CCRS_PropertySetInfo
625             ::impl_getRemainedHandle( ) const
626 {
627     sal_Int32 nHandle = 1;
628 
629     if( !m_pProperties )
630     {
631         OSL_ENSURE( sal_False, "Properties not initialized yet" );
632         return nHandle;
633     }
634     sal_Bool bFound = sal_True;
635     while( bFound )
636     {
637         bFound = sal_False;
638         for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
639         {
640             if( nHandle == (*m_pProperties)[nN].Handle )
641             {
642                 bFound = sal_True;
643                 nHandle++;
644                 break;
645             }
646         }
647     }
648     return nHandle;
649 }
650 
651 //--------------------------------------------------------------------------
652 //--------------------------------------------------------------------------
653 // class CachedContentResultSet
654 //--------------------------------------------------------------------------
655 //--------------------------------------------------------------------------
656 
657 CachedContentResultSet::CachedContentResultSet(
658                   const Reference< XMultiServiceFactory > & xSMgr
659                 , const Reference< XResultSet > & xOrigin
660                 , const Reference< XContentIdentifierMapping > &
661                     xContentIdentifierMapping )
662                 : ContentResultSetWrapper( xOrigin )
663 
664                 , m_xSMgr( xSMgr )
665                 , m_xFetchProvider( NULL )
666                 , m_xFetchProviderForContentAccess( NULL )
667 
668                 , m_xMyPropertySetInfo( NULL )
669                 , m_pMyPropSetInfo( NULL )
670 
671                 , m_xContentIdentifierMapping( xContentIdentifierMapping )
672                 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
673                 , m_bAfterLast( sal_False )
674                 , m_nLastAppliedPos( 0 )
675                 , m_bAfterLastApplied( sal_False )
676                 , m_nKnownCount( 0 )
677                 , m_bFinalCount( sal_False )
678                 , m_nFetchSize(
679                     COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
680                 , m_nFetchDirection(
681                     COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
682 
683                 , m_bLastReadWasFromCache( sal_False )
684                 , m_bLastCachedReadWasNull( sal_True )
685                 , m_aCache( m_xContentIdentifierMapping )
686                 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
687                 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
688                 , m_aCacheContent( m_xContentIdentifierMapping )
689                 , m_bTriedToGetTypeConverter( sal_False )
690                 , m_xTypeConverter( NULL )
691 {
692     m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
693     OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
694 
695     m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
696     OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
697 
698     impl_init();
699 };
700 
701 CachedContentResultSet::~CachedContentResultSet()
702 {
703     impl_deinit();
704     //do not delete m_pMyPropSetInfo, cause it is hold via reference
705 };
706 
707 //--------------------------------------------------------------------------
708 // impl_ methods.
709 //--------------------------------------------------------------------------
710 
711 sal_Bool SAL_CALL CachedContentResultSet
712     ::applyPositionToOrigin( sal_Int32 nRow )
713     throw( SQLException,
714            RuntimeException )
715 {
716     impl_EnsureNotDisposed();
717     //-------------------------------------------------------------------------
718     /**
719     @returns
720         <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
721         the result set.
722     */
723 
724     ReacquireableGuard aGuard( m_aMutex );
725     OSL_ENSURE( nRow >= 0, "only positive values supported" );
726     if( !m_xResultSetOrigin.is() )
727     {
728         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
729         return sal_False;
730     }
731 //  OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
732 
733     sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
734     sal_Bool bAfterLastApplied = m_bAfterLastApplied;
735     sal_Bool bAfterLast = m_bAfterLast;
736     sal_Int32 nForwardOnly = m_nForwardOnly;
737 
738     aGuard.clear();
739 
740     if( bAfterLastApplied || nLastAppliedPos != nRow )
741     {
742         if( nForwardOnly == 1 )
743         {
744             if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
745                 throw SQLException();
746 
747             sal_Int32 nN = nRow - nLastAppliedPos;
748             sal_Int32 nM;
749             for( nM = 0; nN--; nM++ )
750             {
751                 if( !m_xResultSetOrigin->next() )
752                     break;
753             }
754 
755             aGuard.reacquire();
756             m_nLastAppliedPos += nM;
757             m_bAfterLastApplied = nRow != m_nLastAppliedPos;
758             return nRow == m_nLastAppliedPos;
759         }
760 
761         if( !nRow ) //absolute( 0 ) will throw exception
762         {
763             m_xResultSetOrigin->beforeFirst();
764 
765             aGuard.reacquire();
766             m_nLastAppliedPos = 0;
767             m_bAfterLastApplied = sal_False;
768             return sal_False;
769         }
770         try
771         {
772             //move absolute, if !nLastAppliedPos
773             //because move relative would throw exception
774             if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
775             {
776                 sal_Bool bValid = m_xResultSetOrigin->absolute( nRow );
777 
778                 aGuard.reacquire();
779                 m_nLastAppliedPos = nRow;
780                 m_bAfterLastApplied = !bValid;
781                 return bValid;
782             }
783             else
784             {
785                 sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
786 
787                 aGuard.reacquire();
788                 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
789                 m_bAfterLastApplied = !bValid;
790                 return bValid;
791             }
792         }
793         catch( SQLException& rEx )
794         {
795             if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
796             {
797                 sal_Int32 nN = nRow - nLastAppliedPos;
798                 sal_Int32 nM;
799                 for( nM = 0; nN--; nM++ )
800                 {
801                     if( !m_xResultSetOrigin->next() )
802                         break;
803                 }
804 
805                 aGuard.reacquire();
806                 m_nLastAppliedPos += nM;
807                 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
808             }
809             else
810                 throw rEx;
811         }
812 
813         return nRow == m_nLastAppliedPos;
814     }
815     return sal_True;
816 };
817 
818 //--------------------------------------------------------------------------
819 //--------------------------------------------------------------------------
820 //define for fetching data
821 //--------------------------------------------------------------------------
822 //--------------------------------------------------------------------------
823 
824 #define FETCH_XXX( aCache, fetchInterface, fetchMethod )            \
825 sal_Bool bDirection = !!(                                           \
826     nFetchDirection != FetchDirection::REVERSE );                   \
827 FetchResult aResult =                                               \
828     fetchInterface->fetchMethod( nRow, nFetchSize, bDirection );    \
829 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex );              \
830 aCache.loadData( aResult );                                         \
831 sal_Int32 nMax = aCache.getMaxRow();                                \
832 sal_Int32 nCurCount = m_nKnownCount;                                \
833 sal_Bool bIsFinalCount = aCache.hasKnownLast();                     \
834 sal_Bool bCurIsFinalCount = m_bFinalCount;                          \
835 aGuard2.clear();                                                    \
836 if( nMax > nCurCount )                                              \
837     impl_changeRowCount( nCurCount, nMax );                         \
838 if( bIsFinalCount && !bCurIsFinalCount )                            \
839     impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
840 
841 void SAL_CALL CachedContentResultSet
842     ::impl_fetchData( sal_Int32 nRow
843         , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
844         throw( com::sun::star::uno::RuntimeException )
845 {
846     FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
847 }
848 
849 void SAL_CALL CachedContentResultSet
850     ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
851 {
852     OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
853     if( nNew <= nOld )
854         return;
855 
856     //create PropertyChangeEvent and set value
857     PropertyChangeEvent aEvt;
858     {
859         osl::Guard< osl::Mutex > aGuard( m_aMutex );
860         aEvt.Source =  static_cast< XPropertySet * >( this );
861         aEvt.Further = sal_False;
862         aEvt.OldValue <<= nOld;
863         aEvt.NewValue <<= nNew;
864 
865         m_nKnownCount = nNew;
866     }
867 
868     //send PropertyChangeEvent to listeners
869     impl_notifyPropertyChangeListeners( aEvt );
870 }
871 
872 void SAL_CALL CachedContentResultSet
873     ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew )
874 {
875     OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
876     if( ! (!bOld && bNew ) )
877         return;
878 
879     //create PropertyChangeEvent and set value
880     PropertyChangeEvent aEvt;
881     {
882         osl::Guard< osl::Mutex > aGuard( m_aMutex );
883         aEvt.Source =  static_cast< XPropertySet * >( this );
884         aEvt.Further = sal_False;
885         aEvt.OldValue <<= bOld;
886         aEvt.NewValue <<= bNew;
887 
888         m_bFinalCount = bNew;
889     }
890 
891     //send PropertyChangeEvent to listeners
892     impl_notifyPropertyChangeListeners( aEvt );
893 }
894 
895 sal_Bool SAL_CALL CachedContentResultSet
896     ::impl_isKnownValidPosition( sal_Int32 nRow )
897 {
898     return m_nKnownCount && nRow
899             && nRow <= m_nKnownCount;
900 }
901 
902 sal_Bool SAL_CALL CachedContentResultSet
903     ::impl_isKnownInvalidPosition( sal_Int32 nRow )
904 {
905     if( !nRow )
906         return sal_True;
907     if( !m_bFinalCount )
908         return sal_False;
909     return nRow > m_nKnownCount;
910 }
911 
912 
913 //virtual
914 void SAL_CALL CachedContentResultSet
915     ::impl_initPropertySetInfo()
916 {
917     ContentResultSetWrapper::impl_initPropertySetInfo();
918 
919     osl::Guard< osl::Mutex > aGuard( m_aMutex );
920     if( m_pMyPropSetInfo )
921         return;
922     m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
923     m_xMyPropertySetInfo = m_pMyPropSetInfo;
924     m_xPropertySetInfo = m_xMyPropertySetInfo;
925 }
926 
927 //--------------------------------------------------------------------------
928 // XInterface methods. ( inherited )
929 //--------------------------------------------------------------------------
930 XINTERFACE_COMMON_IMPL( CachedContentResultSet )
931 
932 Any SAL_CALL CachedContentResultSet
933     ::queryInterface( const Type&  rType )
934     throw ( RuntimeException )
935 {
936     //list all interfaces inclusive baseclasses of interfaces
937 
938     Any aRet = ContentResultSetWrapper::queryInterface( rType );
939     if( aRet.hasValue() )
940         return aRet;
941 
942     aRet = cppu::queryInterface( rType,
943                 static_cast< XTypeProvider* >( this ),
944                 static_cast< XServiceInfo* >( this ) );
945 
946     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
947 }
948 
949 //--------------------------------------------------------------------------
950 // XTypeProvider methods.
951 //--------------------------------------------------------------------------
952 //list all interfaces exclusive baseclasses
953 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
954                     , XTypeProvider
955                     , XServiceInfo
956                     , XComponent
957                     , XCloseable
958                     , XResultSetMetaDataSupplier
959                     , XPropertySet
960 
961                     , XPropertyChangeListener
962                     , XVetoableChangeListener
963 
964                     , XContentAccess
965 
966                     , XResultSet
967                     , XRow );
968 
969 //--------------------------------------------------------------------------
970 // XServiceInfo methods.
971 //--------------------------------------------------------------------------
972 
973 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
974                            OUString::createFromAscii(
975                             "com.sun.star.comp.ucb.CachedContentResultSet" ),
976                            OUString::createFromAscii(
977                             CACHED_CONTENT_RESULTSET_SERVICE_NAME ) );
978 
979 //--------------------------------------------------------------------------
980 // XPropertySet methods. ( inherited )
981 //--------------------------------------------------------------------------
982 
983 // virtual
984 void SAL_CALL CachedContentResultSet
985     ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
986     throw( UnknownPropertyException,
987            PropertyVetoException,
988            IllegalArgumentException,
989            WrappedTargetException,
990            RuntimeException )
991 {
992     impl_EnsureNotDisposed();
993 
994     if( !getPropertySetInfo().is() )
995     {
996         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
997         throw UnknownPropertyException();
998     }
999 
1000     Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
1001         //throws UnknownPropertyException, if so
1002 
1003     if( aProp.Attributes & PropertyAttribute::READONLY )
1004     {
1005         //It is assumed, that the properties
1006         //'RowCount' and 'IsRowCountFinal' are readonly!
1007         throw IllegalArgumentException();
1008     }
1009     if( aProp.Name == CCRS_PropertySetInfo
1010                         ::m_aPropertyNameForFetchDirection )
1011     {
1012         //check value
1013         sal_Int32 nNew;
1014         if( !( aValue >>= nNew ) )
1015         {
1016             throw IllegalArgumentException();
1017         }
1018 
1019         if( nNew == FetchDirection::UNKNOWN )
1020         {
1021             nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1022         }
1023         else if( !( nNew == FetchDirection::FORWARD
1024                 || nNew == FetchDirection::REVERSE ) )
1025         {
1026             throw IllegalArgumentException();
1027         }
1028 
1029         //create PropertyChangeEvent and set value
1030         PropertyChangeEvent aEvt;
1031         {
1032             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1033             aEvt.Source =  static_cast< XPropertySet * >( this );
1034             aEvt.PropertyName = aPropertyName;
1035             aEvt.Further = sal_False;
1036             aEvt.PropertyHandle = m_pMyPropSetInfo->
1037                                     m_nFetchDirectionPropertyHandle;
1038             aEvt.OldValue <<= m_nFetchDirection;
1039             aEvt.NewValue <<= nNew;
1040 
1041             m_nFetchDirection = nNew;
1042         }
1043 
1044         //send PropertyChangeEvent to listeners
1045         impl_notifyPropertyChangeListeners( aEvt );
1046     }
1047     else if( aProp.Name == CCRS_PropertySetInfo
1048                         ::m_aPropertyNameForFetchSize )
1049     {
1050         //check value
1051         sal_Int32 nNew;
1052         if( !( aValue >>= nNew ) )
1053         {
1054             throw IllegalArgumentException();
1055         }
1056 
1057         if( nNew < 0 )
1058         {
1059             nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1060         }
1061 
1062         //create PropertyChangeEvent and set value
1063         PropertyChangeEvent aEvt;
1064         {
1065             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1066             aEvt.Source =  static_cast< XPropertySet * >( this );
1067             aEvt.PropertyName = aPropertyName;
1068             aEvt.Further = sal_False;
1069             aEvt.PropertyHandle = m_pMyPropSetInfo->
1070                                     m_nFetchSizePropertyHandle;
1071             aEvt.OldValue <<= m_nFetchSize;
1072             aEvt.NewValue <<= nNew;
1073 
1074             m_nFetchSize = nNew;
1075         }
1076 
1077         //send PropertyChangeEvent to listeners
1078         impl_notifyPropertyChangeListeners( aEvt );
1079     }
1080     else
1081     {
1082         impl_init_xPropertySetOrigin();
1083         {
1084             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1085             if( !m_xPropertySetOrigin.is() )
1086             {
1087                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1088                 return;
1089             }
1090         }
1091         m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1092     }
1093 }
1094 
1095 //--------------------------------------------------------------------------
1096 // virtual
1097 Any SAL_CALL CachedContentResultSet
1098     ::getPropertyValue( const OUString& rPropertyName )
1099     throw( UnknownPropertyException,
1100            WrappedTargetException,
1101            RuntimeException )
1102 {
1103     impl_EnsureNotDisposed();
1104 
1105     if( !getPropertySetInfo().is() )
1106     {
1107         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1108         throw UnknownPropertyException();
1109     }
1110 
1111     Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1112         //throws UnknownPropertyException, if so
1113 
1114     Any aValue;
1115     if( rPropertyName == CCRS_PropertySetInfo
1116                         ::m_aPropertyNameForCount )
1117     {
1118         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1119         aValue <<= m_nKnownCount;
1120     }
1121     else if( rPropertyName == CCRS_PropertySetInfo
1122                             ::m_aPropertyNameForFinalCount )
1123     {
1124         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1125         aValue <<= m_bFinalCount;
1126     }
1127     else if( rPropertyName == CCRS_PropertySetInfo
1128                             ::m_aPropertyNameForFetchSize )
1129     {
1130         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1131         aValue <<= m_nFetchSize;
1132     }
1133     else if( rPropertyName == CCRS_PropertySetInfo
1134                             ::m_aPropertyNameForFetchDirection )
1135     {
1136         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1137         aValue <<= m_nFetchDirection;
1138     }
1139     else
1140     {
1141         impl_init_xPropertySetOrigin();
1142         {
1143             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1144             if( !m_xPropertySetOrigin.is() )
1145             {
1146                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1147                 throw UnknownPropertyException();
1148             }
1149         }
1150         aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1151     }
1152     return aValue;
1153 }
1154 
1155 //--------------------------------------------------------------------------
1156 // own methods.  ( inherited )
1157 //--------------------------------------------------------------------------
1158 
1159 //virtual
1160 void SAL_CALL CachedContentResultSet
1161     ::impl_disposing( const EventObject& rEventObject )
1162     throw( RuntimeException )
1163 {
1164     {
1165         impl_EnsureNotDisposed();
1166         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1167         //release all references to the broadcaster:
1168         m_xFetchProvider.clear();
1169         m_xFetchProviderForContentAccess.clear();
1170     }
1171     ContentResultSetWrapper::impl_disposing( rEventObject );
1172 }
1173 
1174 //virtual
1175 void SAL_CALL CachedContentResultSet
1176     ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1177     throw( RuntimeException )
1178 {
1179     impl_EnsureNotDisposed();
1180 
1181     PropertyChangeEvent aEvt( rEvt );
1182     aEvt.Source = static_cast< XPropertySet * >( this );
1183     aEvt.Further = sal_False;
1184     //---------
1185 
1186     if( CCRS_PropertySetInfo
1187             ::impl_isMyPropertyName( rEvt.PropertyName ) )
1188     {
1189         //don't notify foreign events on fetchsize and fetchdirection
1190         if( aEvt.PropertyName == CCRS_PropertySetInfo
1191                                 ::m_aPropertyNameForFetchSize
1192         || aEvt.PropertyName == CCRS_PropertySetInfo
1193                                 ::m_aPropertyNameForFetchDirection )
1194             return;
1195 
1196         //adjust my props 'RowCount' and 'IsRowCountFinal'
1197         if( aEvt.PropertyName == CCRS_PropertySetInfo
1198                             ::m_aPropertyNameForCount )
1199         {//RowCount changed
1200 
1201             //check value
1202             sal_Int32 nNew = 0;
1203             if( !( aEvt.NewValue >>= nNew ) )
1204             {
1205                 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1206                 return;
1207             }
1208 
1209             impl_changeRowCount( m_nKnownCount, nNew );
1210         }
1211         else if( aEvt.PropertyName == CCRS_PropertySetInfo
1212                                 ::m_aPropertyNameForFinalCount )
1213         {//IsRowCountFinal changed
1214 
1215             //check value
1216             sal_Bool bNew = sal_False;
1217             if( !( aEvt.NewValue >>= bNew ) )
1218             {
1219                 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1220                 return;
1221             }
1222             impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1223         }
1224         return;
1225     }
1226 
1227     //-----------
1228     impl_notifyPropertyChangeListeners( aEvt );
1229 }
1230 
1231 
1232 //virtual
1233 void SAL_CALL CachedContentResultSet
1234     ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1235     throw( PropertyVetoException,
1236            RuntimeException )
1237 {
1238     impl_EnsureNotDisposed();
1239 
1240     //don't notify events on my properties, cause they are not vetoable
1241     if( CCRS_PropertySetInfo
1242             ::impl_isMyPropertyName( rEvt.PropertyName ) )
1243     {
1244         return;
1245     }
1246 
1247 
1248     PropertyChangeEvent aEvt( rEvt );
1249     aEvt.Source = static_cast< XPropertySet * >( this );
1250     aEvt.Further = sal_False;
1251 
1252     impl_notifyVetoableChangeListeners( aEvt );
1253 }
1254 
1255 //--------------------------------------------------------------------------
1256 // XContentAccess methods. ( inherited ) ( -- position dependent )
1257 //--------------------------------------------------------------------------
1258 
1259 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE )              \
1260 impl_EnsureNotDisposed();                                   \
1261 ReacquireableGuard aGuard( m_aMutex );                      \
1262 sal_Int32 nRow = m_nRow;                                    \
1263 sal_Int32 nFetchSize = m_nFetchSize;                        \
1264 sal_Int32 nFetchDirection = m_nFetchDirection;              \
1265 if( !m_aCache##XXX.hasRow( nRow ) )                         \
1266 {                                                           \
1267     if( !m_aCache##XXX.hasCausedException( nRow ) )         \
1268 {                                                           \
1269         if( !m_xFetchProviderForContentAccess.is() )        \
1270         {                                                   \
1271             OSL_ENSURE( sal_False, "broadcaster was disposed already" );\
1272             throw RuntimeException();                       \
1273         }                                                   \
1274         aGuard.clear();                                     \
1275         if( impl_isForwardOnly() )                          \
1276             applyPositionToOrigin( nRow );                  \
1277                                                             \
1278         FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1279     }                                                       \
1280     aGuard.reacquire();                                     \
1281     if( !m_aCache##XXX.hasRow( nRow ) )                     \
1282     {                                                       \
1283         aGuard.clear();                                     \
1284         applyPositionToOrigin( nRow );                      \
1285         TYPE aRet = ContentResultSetWrapper::queryXXX();    \
1286         if( m_xContentIdentifierMapping.is() )              \
1287             return m_xContentIdentifierMapping->map##XXX( aRet );\
1288         return aRet;                                        \
1289     }                                                       \
1290 }                                                           \
1291 return m_aCache##XXX.get##XXX( nRow );
1292 
1293 //--------------------------------------------------------------------------
1294 // virtual
1295 OUString SAL_CALL CachedContentResultSet
1296     ::queryContentIdentifierString()
1297     throw( RuntimeException )
1298 {
1299     XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1300 }
1301 
1302 //--------------------------------------------------------------------------
1303 // virtual
1304 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
1305     ::queryContentIdentifier()
1306     throw( RuntimeException )
1307 {
1308     XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1309 }
1310 
1311 //--------------------------------------------------------------------------
1312 // virtual
1313 Reference< XContent > SAL_CALL CachedContentResultSet
1314     ::queryContent()
1315     throw( RuntimeException )
1316 {
1317     XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1318 }
1319 
1320 //-----------------------------------------------------------------
1321 // XResultSet methods. ( inherited )
1322 //-----------------------------------------------------------------
1323 //virtual
1324 
1325 sal_Bool SAL_CALL CachedContentResultSet
1326     ::next()
1327     throw( SQLException,
1328            RuntimeException )
1329 {
1330     impl_EnsureNotDisposed();
1331 
1332     ReacquireableGuard aGuard( m_aMutex );
1333     //after last
1334     if( m_bAfterLast )
1335         return sal_False;
1336     //last
1337     aGuard.clear();
1338     if( isLast() )
1339     {
1340         aGuard.reacquire();
1341         m_nRow++;
1342         m_bAfterLast = sal_True;
1343         return sal_False;
1344     }
1345     aGuard.reacquire();
1346     //known valid position
1347     if( impl_isKnownValidPosition( m_nRow + 1 ) )
1348     {
1349         m_nRow++;
1350         return sal_True;
1351     }
1352 
1353     //unknown position
1354     sal_Int32 nRow = m_nRow;
1355     aGuard.clear();
1356 
1357     sal_Bool bValid = applyPositionToOrigin( nRow + 1 );
1358 
1359     aGuard.reacquire();
1360     m_nRow = nRow + 1;
1361     m_bAfterLast = !bValid;
1362     return bValid;
1363 }
1364 
1365 //virtual
1366 sal_Bool SAL_CALL CachedContentResultSet
1367     ::previous()
1368     throw( SQLException,
1369            RuntimeException )
1370 {
1371     impl_EnsureNotDisposed();
1372 
1373     if( impl_isForwardOnly() )
1374         throw SQLException();
1375 
1376     ReacquireableGuard aGuard( m_aMutex );
1377     //before first ?:
1378     if( !m_bAfterLast && !m_nRow )
1379         return sal_False;
1380     //first ?:
1381     if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1382     {
1383         m_nRow--;
1384         m_bAfterLast = sal_False;
1385         return sal_False;
1386     }
1387     //known valid position ?:
1388     if( impl_isKnownValidPosition( m_nRow - 1 ) )
1389     {
1390         m_nRow--;
1391         m_bAfterLast = sal_False;
1392         return sal_True;
1393     }
1394     //unknown position:
1395     sal_Int32 nRow = m_nRow;
1396     aGuard.clear();
1397 
1398     sal_Bool bValid = applyPositionToOrigin( nRow - 1  );
1399 
1400     aGuard.reacquire();
1401     m_nRow = nRow - 1;
1402     m_bAfterLast = sal_False;
1403     return bValid;
1404 }
1405 
1406 //virtual
1407 sal_Bool SAL_CALL CachedContentResultSet
1408     ::absolute( sal_Int32 row )
1409     throw( SQLException,
1410            RuntimeException )
1411 {
1412     impl_EnsureNotDisposed();
1413 
1414     if( !row )
1415         throw SQLException();
1416 
1417     if( impl_isForwardOnly() )
1418         throw SQLException();
1419 
1420     ReacquireableGuard aGuard( m_aMutex );
1421 
1422     if( !m_xResultSetOrigin.is() )
1423     {
1424         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1425         return sal_False;
1426     }
1427     if( row < 0 )
1428     {
1429         if( m_bFinalCount )
1430         {
1431             sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1432             sal_Bool bValid = sal_True;
1433             if( nNewRow <= 0 )
1434             {
1435                 nNewRow = 0;
1436                 bValid = sal_False;
1437             }
1438             m_nRow = nNewRow;
1439             m_bAfterLast = sal_False;
1440             return bValid;
1441         }
1442         //unknown final count:
1443         aGuard.clear();
1444 
1445         // Solaris has problems catching or propagating derived exceptions
1446         // when only the base class is known, so make ResultSetException
1447         // (derived from SQLException) known here:
1448         sal_Bool bValid;
1449         try
1450         {
1451             bValid = m_xResultSetOrigin->absolute( row );
1452         }
1453         catch (ResultSetException &)
1454         {
1455             throw;
1456         }
1457 
1458         aGuard.reacquire();
1459         if( m_bFinalCount )
1460         {
1461             sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1462             if( nNewRow < 0 )
1463                 nNewRow = 0;
1464             m_nLastAppliedPos = nNewRow;
1465             m_nRow = nNewRow;
1466             m_bAfterLastApplied = m_bAfterLast = sal_False;
1467             return bValid;
1468         }
1469         aGuard.clear();
1470 
1471         sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1472 
1473         aGuard.reacquire();
1474         m_nLastAppliedPos = nCurRow;
1475         m_nRow = nCurRow;
1476         m_bAfterLast = sal_False;
1477         return nCurRow != 0;
1478     }
1479     //row > 0:
1480     if( m_bFinalCount )
1481     {
1482         if( row > m_nKnownCount )
1483         {
1484             m_nRow = m_nKnownCount + 1;
1485             m_bAfterLast = sal_True;
1486             return sal_False;
1487         }
1488         m_nRow = row;
1489         m_bAfterLast = sal_False;
1490         return sal_True;
1491     }
1492     //unknown new position:
1493     aGuard.clear();
1494 
1495     sal_Bool bValid = m_xResultSetOrigin->absolute( row );
1496 
1497     aGuard.reacquire();
1498     if( m_bFinalCount )
1499     {
1500         sal_Int32 nNewRow = row;
1501         if( nNewRow > m_nKnownCount )
1502         {
1503             nNewRow = m_nKnownCount + 1;
1504             m_bAfterLastApplied = m_bAfterLast = sal_True;
1505         }
1506         else
1507             m_bAfterLastApplied = m_bAfterLast = sal_False;
1508 
1509         m_nLastAppliedPos = nNewRow;
1510         m_nRow = nNewRow;
1511         return bValid;
1512     }
1513     aGuard.clear();
1514 
1515     sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1516     sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1517 
1518     aGuard.reacquire();
1519     m_nLastAppliedPos = nCurRow;
1520     m_nRow = nCurRow;
1521     m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1522     return nCurRow && !bIsAfterLast;
1523 }
1524 
1525 //virtual
1526 sal_Bool SAL_CALL CachedContentResultSet
1527     ::relative( sal_Int32 rows )
1528     throw( SQLException,
1529            RuntimeException )
1530 {
1531     impl_EnsureNotDisposed();
1532 
1533     if( impl_isForwardOnly() )
1534         throw SQLException();
1535 
1536     ReacquireableGuard aGuard( m_aMutex );
1537     if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1538         throw SQLException();
1539 
1540     if( !rows )
1541         return sal_True;
1542 
1543     sal_Int32 nNewRow = m_nRow + rows;
1544         if( nNewRow < 0 )
1545             nNewRow = 0;
1546 
1547     if( impl_isKnownValidPosition( nNewRow ) )
1548     {
1549         m_nRow = nNewRow;
1550         m_bAfterLast = sal_False;
1551         return sal_True;
1552     }
1553     else
1554     {
1555         //known invalid new position:
1556         if( nNewRow == 0 )
1557         {
1558             m_bAfterLast = sal_False;
1559             m_nRow = 0;
1560             return sal_False;
1561         }
1562         if( m_bFinalCount && nNewRow > m_nKnownCount )
1563         {
1564             m_bAfterLast = sal_True;
1565             m_nRow = m_nKnownCount + 1;
1566             return sal_False;
1567         }
1568         //unknown new position:
1569         aGuard.clear();
1570         sal_Bool bValid = applyPositionToOrigin( nNewRow );
1571 
1572         aGuard.reacquire();
1573         m_nRow = nNewRow;
1574         m_bAfterLast = !bValid && nNewRow > 0;
1575         return bValid;
1576     }
1577 }
1578 
1579 
1580 //virtual
1581 sal_Bool SAL_CALL CachedContentResultSet
1582     ::first()
1583     throw( SQLException,
1584            RuntimeException )
1585 {
1586     impl_EnsureNotDisposed();
1587 
1588     if( impl_isForwardOnly() )
1589         throw SQLException();
1590 
1591     ReacquireableGuard aGuard( m_aMutex );
1592     if( impl_isKnownValidPosition( 1 ) )
1593     {
1594         m_nRow = 1;
1595         m_bAfterLast = sal_False;
1596         return sal_True;
1597     }
1598     if( impl_isKnownInvalidPosition( 1 ) )
1599     {
1600         m_nRow = 1;
1601         m_bAfterLast = sal_False;
1602         return sal_False;
1603     }
1604     //unknown position
1605     aGuard.clear();
1606 
1607     sal_Bool bValid = applyPositionToOrigin( 1 );
1608 
1609     aGuard.reacquire();
1610     m_nRow = 1;
1611     m_bAfterLast = sal_False;
1612     return bValid;
1613 }
1614 
1615 //virtual
1616 sal_Bool SAL_CALL CachedContentResultSet
1617     ::last()
1618     throw( SQLException,
1619            RuntimeException )
1620 {
1621     impl_EnsureNotDisposed();
1622 
1623     if( impl_isForwardOnly() )
1624         throw SQLException();
1625 
1626     ReacquireableGuard aGuard( m_aMutex );
1627     if( m_bFinalCount )
1628     {
1629         m_nRow = m_nKnownCount;
1630         m_bAfterLast = sal_False;
1631         return m_nKnownCount != 0;
1632     }
1633     //unknown position
1634     if( !m_xResultSetOrigin.is() )
1635     {
1636         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1637         return sal_False;
1638     }
1639     aGuard.clear();
1640 
1641     sal_Bool bValid = m_xResultSetOrigin->last();
1642 
1643     aGuard.reacquire();
1644     m_bAfterLastApplied = m_bAfterLast = sal_False;
1645     if( m_bFinalCount )
1646     {
1647         m_nLastAppliedPos = m_nKnownCount;
1648         m_nRow = m_nKnownCount;
1649         return bValid;
1650     }
1651     aGuard.clear();
1652 
1653     sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1654 
1655     aGuard.reacquire();
1656     m_nLastAppliedPos = nCurRow;
1657     m_nRow = nCurRow;
1658     OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1659     m_nKnownCount = nCurRow;
1660     m_bFinalCount = sal_True;
1661     return nCurRow != 0;
1662 }
1663 
1664 //virtual
1665 void SAL_CALL CachedContentResultSet
1666     ::beforeFirst()
1667     throw( SQLException,
1668            RuntimeException )
1669 {
1670     impl_EnsureNotDisposed();
1671 
1672     if( impl_isForwardOnly() )
1673         throw SQLException();
1674 
1675     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1676     m_nRow = 0;
1677     m_bAfterLast = sal_False;
1678 }
1679 
1680 //virtual
1681 void SAL_CALL CachedContentResultSet
1682     ::afterLast()
1683     throw( SQLException,
1684            RuntimeException )
1685 {
1686     impl_EnsureNotDisposed();
1687 
1688     if( impl_isForwardOnly() )
1689         throw SQLException();
1690 
1691     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1692     m_nRow = 1;
1693     m_bAfterLast = sal_True;
1694 }
1695 
1696 //virtual
1697 sal_Bool SAL_CALL CachedContentResultSet
1698     ::isAfterLast()
1699     throw( SQLException,
1700            RuntimeException )
1701 {
1702     impl_EnsureNotDisposed();
1703 
1704     ReacquireableGuard aGuard( m_aMutex );
1705     if( !m_bAfterLast )
1706         return sal_False;
1707     if( m_nKnownCount )
1708         return m_bAfterLast;
1709     if( m_bFinalCount )
1710         return sal_False;
1711 
1712     if( !m_xResultSetOrigin.is() )
1713     {
1714         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1715         return sal_False;
1716     }
1717     aGuard.clear();
1718 
1719     //find out whethter the original resultset contains rows or not
1720     m_xResultSetOrigin->afterLast();
1721 
1722     aGuard.reacquire();
1723     m_bAfterLastApplied = sal_True;
1724     aGuard.clear();
1725 
1726     return m_xResultSetOrigin->isAfterLast();
1727 }
1728 
1729 //virtual
1730 sal_Bool SAL_CALL CachedContentResultSet
1731     ::isBeforeFirst()
1732     throw( SQLException,
1733            RuntimeException )
1734 {
1735     impl_EnsureNotDisposed();
1736 
1737     ReacquireableGuard aGuard( m_aMutex );
1738     if( m_bAfterLast )
1739         return sal_False;
1740     if( m_nRow )
1741         return sal_False;
1742     if( m_nKnownCount )
1743         return !m_nRow;
1744     if( m_bFinalCount )
1745         return sal_False;
1746 
1747     if( !m_xResultSetOrigin.is() )
1748     {
1749         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1750         return sal_False;
1751     }
1752     aGuard.clear();
1753 
1754     //find out whethter the original resultset contains rows or not
1755     m_xResultSetOrigin->beforeFirst();
1756 
1757     aGuard.reacquire();
1758     m_bAfterLastApplied = sal_False;
1759     m_nLastAppliedPos = 0;
1760     aGuard.clear();
1761 
1762     return m_xResultSetOrigin->isBeforeFirst();
1763 }
1764 
1765 //virtual
1766 sal_Bool SAL_CALL CachedContentResultSet
1767     ::isFirst()
1768     throw( SQLException,
1769            RuntimeException )
1770 {
1771     impl_EnsureNotDisposed();
1772 
1773     sal_Int32 nRow = 0;
1774     Reference< XResultSet > xResultSetOrigin;
1775 
1776     {
1777         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1778         if( m_bAfterLast )
1779             return sal_False;
1780         if( m_nRow != 1 )
1781             return sal_False;
1782         if( m_nKnownCount )
1783             return m_nRow == 1;
1784         if( m_bFinalCount )
1785             return sal_False;
1786 
1787         nRow = m_nRow;
1788         xResultSetOrigin = m_xResultSetOrigin;
1789     }
1790 
1791     //need to ask origin
1792     {
1793         if( applyPositionToOrigin( nRow ) )
1794             return xResultSetOrigin->isFirst();
1795         else
1796             return sal_False;
1797     }
1798 }
1799 
1800 //virtual
1801 sal_Bool SAL_CALL CachedContentResultSet
1802     ::isLast()
1803     throw( SQLException,
1804            RuntimeException )
1805 {
1806     impl_EnsureNotDisposed();
1807 
1808     sal_Int32 nRow = 0;
1809     Reference< XResultSet > xResultSetOrigin;
1810     {
1811         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1812         if( m_bAfterLast )
1813             return sal_False;
1814         if( m_nRow < m_nKnownCount )
1815             return sal_False;
1816         if( m_bFinalCount )
1817             return m_nKnownCount && m_nRow == m_nKnownCount;
1818 
1819         nRow = m_nRow;
1820         xResultSetOrigin = m_xResultSetOrigin;
1821     }
1822 
1823     //need to ask origin
1824     {
1825         if( applyPositionToOrigin( nRow ) )
1826             return xResultSetOrigin->isLast();
1827         else
1828             return sal_False;
1829     }
1830 }
1831 
1832 
1833 //virtual
1834 sal_Int32 SAL_CALL CachedContentResultSet
1835     ::getRow()
1836     throw( SQLException,
1837            RuntimeException )
1838 {
1839     impl_EnsureNotDisposed();
1840 
1841     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1842     if( m_bAfterLast )
1843         return 0;
1844     return m_nRow;
1845 }
1846 
1847 //virtual
1848 void SAL_CALL CachedContentResultSet
1849     ::refreshRow()
1850     throw( SQLException,
1851            RuntimeException )
1852 {
1853     impl_EnsureNotDisposed();
1854 
1855     //the ContentResultSet is static and will not change
1856     //therefore we don't need to reload anything
1857 }
1858 
1859 //virtual
1860 sal_Bool SAL_CALL CachedContentResultSet
1861     ::rowUpdated()
1862     throw( SQLException,
1863            RuntimeException )
1864 {
1865     impl_EnsureNotDisposed();
1866 
1867     //the ContentResultSet is static and will not change
1868     return sal_False;
1869 }
1870 //virtual
1871 sal_Bool SAL_CALL CachedContentResultSet
1872     ::rowInserted()
1873     throw( SQLException,
1874            RuntimeException )
1875 {
1876     impl_EnsureNotDisposed();
1877 
1878     //the ContentResultSet is static and will not change
1879     return sal_False;
1880 }
1881 
1882 //virtual
1883 sal_Bool SAL_CALL CachedContentResultSet
1884     ::rowDeleted()
1885     throw( SQLException,
1886            RuntimeException )
1887 {
1888     impl_EnsureNotDisposed();
1889 
1890     //the ContentResultSet is static and will not change
1891     return sal_False;
1892 }
1893 
1894 //virtual
1895 Reference< XInterface > SAL_CALL CachedContentResultSet
1896     ::getStatement()
1897     throw( SQLException,
1898            RuntimeException )
1899 {
1900     impl_EnsureNotDisposed();
1901     //@todo ?return anything
1902     return Reference< XInterface >();
1903 }
1904 
1905 //-----------------------------------------------------------------
1906 // XRow methods. ( inherited )
1907 //-----------------------------------------------------------------
1908 
1909 //virtual
1910 sal_Bool SAL_CALL CachedContentResultSet
1911     ::wasNull()
1912     throw( SQLException,
1913            RuntimeException )
1914 {
1915     impl_EnsureNotDisposed();
1916     impl_init_xRowOrigin();
1917     {
1918         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1919         if( m_bLastReadWasFromCache )
1920             return m_bLastCachedReadWasNull;
1921         if( !m_xRowOrigin.is() )
1922         {
1923             OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1924             return sal_False;
1925         }
1926     }
1927     return m_xRowOrigin->wasNull();
1928 }
1929 
1930 //virtual
1931 rtl::OUString SAL_CALL CachedContentResultSet
1932     ::getString( sal_Int32 columnIndex )
1933     throw( SQLException,
1934            RuntimeException )
1935 {
1936     XROW_GETXXX( getString, OUString );
1937 }
1938 
1939 //virtual
1940 sal_Bool SAL_CALL CachedContentResultSet
1941     ::getBoolean( sal_Int32 columnIndex )
1942     throw( SQLException,
1943            RuntimeException )
1944 {
1945     XROW_GETXXX( getBoolean, sal_Bool );
1946 }
1947 
1948 //virtual
1949 sal_Int8 SAL_CALL CachedContentResultSet
1950     ::getByte( sal_Int32 columnIndex )
1951     throw( SQLException,
1952            RuntimeException )
1953 {
1954     XROW_GETXXX( getByte, sal_Int8 );
1955 }
1956 
1957 //virtual
1958 sal_Int16 SAL_CALL CachedContentResultSet
1959     ::getShort( sal_Int32 columnIndex )
1960     throw( SQLException,
1961            RuntimeException )
1962 {
1963     XROW_GETXXX( getShort, sal_Int16 );
1964 }
1965 
1966 //virtual
1967 sal_Int32 SAL_CALL CachedContentResultSet
1968     ::getInt( sal_Int32 columnIndex )
1969     throw( SQLException,
1970            RuntimeException )
1971 {
1972     XROW_GETXXX( getInt, sal_Int32 );
1973 }
1974 
1975 //virtual
1976 sal_Int64 SAL_CALL CachedContentResultSet
1977     ::getLong( sal_Int32 columnIndex )
1978     throw( SQLException,
1979            RuntimeException )
1980 {
1981     XROW_GETXXX( getLong, sal_Int64 );
1982 }
1983 
1984 //virtual
1985 float SAL_CALL CachedContentResultSet
1986     ::getFloat( sal_Int32 columnIndex )
1987     throw( SQLException,
1988            RuntimeException )
1989 {
1990     XROW_GETXXX( getFloat, float );
1991 }
1992 
1993 //virtual
1994 double SAL_CALL CachedContentResultSet
1995     ::getDouble( sal_Int32 columnIndex )
1996     throw( SQLException,
1997            RuntimeException )
1998 {
1999     XROW_GETXXX( getDouble, double );
2000 }
2001 
2002 //virtual
2003 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
2004     ::getBytes( sal_Int32 columnIndex )
2005     throw( SQLException,
2006            RuntimeException )
2007 {
2008     XROW_GETXXX( getBytes, Sequence< sal_Int8 > );
2009 }
2010 
2011 //virtual
2012 Date SAL_CALL CachedContentResultSet
2013     ::getDate( sal_Int32 columnIndex )
2014     throw( SQLException,
2015            RuntimeException )
2016 {
2017     XROW_GETXXX( getDate, Date );
2018 }
2019 
2020 //virtual
2021 Time SAL_CALL CachedContentResultSet
2022     ::getTime( sal_Int32 columnIndex )
2023     throw( SQLException,
2024            RuntimeException )
2025 {
2026     XROW_GETXXX( getTime, Time );
2027 }
2028 
2029 //virtual
2030 DateTime SAL_CALL CachedContentResultSet
2031     ::getTimestamp( sal_Int32 columnIndex )
2032     throw( SQLException,
2033            RuntimeException )
2034 {
2035     XROW_GETXXX( getTimestamp, DateTime );
2036 }
2037 
2038 //virtual
2039 Reference< com::sun::star::io::XInputStream >
2040     SAL_CALL CachedContentResultSet
2041     ::getBinaryStream( sal_Int32 columnIndex )
2042     throw( SQLException,
2043            RuntimeException )
2044 {
2045     XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > );
2046 }
2047 
2048 //virtual
2049 Reference< com::sun::star::io::XInputStream >
2050     SAL_CALL CachedContentResultSet
2051     ::getCharacterStream( sal_Int32 columnIndex )
2052     throw( SQLException,
2053            RuntimeException )
2054 {
2055     XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > );
2056 }
2057 
2058 //virtual
2059 Any SAL_CALL CachedContentResultSet
2060     ::getObject( sal_Int32 columnIndex,
2061            const Reference<
2062             com::sun::star::container::XNameAccess >& typeMap )
2063     throw( SQLException,
2064            RuntimeException )
2065 {
2066     //if you change this macro please pay attention to
2067     //define XROW_GETXXX, where this is similar implemented
2068 
2069     ReacquireableGuard aGuard( m_aMutex );
2070     sal_Int32 nRow = m_nRow;
2071     sal_Int32 nFetchSize = m_nFetchSize;
2072     sal_Int32 nFetchDirection = m_nFetchDirection;
2073     if( !m_aCache.hasRow( nRow ) )
2074     {
2075         if( !m_aCache.hasCausedException( nRow ) )
2076         {
2077             if( !m_xFetchProvider.is() )
2078             {
2079                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
2080                 return Any();
2081             }
2082             aGuard.clear();
2083 
2084             impl_fetchData( nRow, nFetchSize, nFetchDirection );
2085         }
2086         aGuard.reacquire();
2087         if( !m_aCache.hasRow( nRow ) )
2088         {
2089             m_bLastReadWasFromCache = sal_False;
2090             aGuard.clear();
2091             applyPositionToOrigin( nRow );
2092             impl_init_xRowOrigin();
2093             return m_xRowOrigin->getObject( columnIndex, typeMap );
2094         }
2095     }
2096     //@todo: pay attention to typeMap
2097     const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2098     Any aRet;
2099     m_bLastReadWasFromCache = sal_True;
2100     m_bLastCachedReadWasNull = !( rValue >>= aRet );
2101     return aRet;
2102 }
2103 
2104 //virtual
2105 Reference< XRef > SAL_CALL CachedContentResultSet
2106     ::getRef( sal_Int32 columnIndex )
2107     throw( SQLException,
2108            RuntimeException )
2109 {
2110     XROW_GETXXX( getRef, Reference< XRef > );
2111 }
2112 
2113 //virtual
2114 Reference< XBlob > SAL_CALL CachedContentResultSet
2115     ::getBlob( sal_Int32 columnIndex )
2116     throw( SQLException,
2117            RuntimeException )
2118 {
2119     XROW_GETXXX( getBlob, Reference< XBlob > );
2120 }
2121 
2122 //virtual
2123 Reference< XClob > SAL_CALL CachedContentResultSet
2124     ::getClob( sal_Int32 columnIndex )
2125     throw( SQLException,
2126            RuntimeException )
2127 {
2128     XROW_GETXXX( getClob, Reference< XClob > );
2129 }
2130 
2131 //virtual
2132 Reference< XArray > SAL_CALL CachedContentResultSet
2133     ::getArray( sal_Int32 columnIndex )
2134     throw( SQLException,
2135            RuntimeException )
2136 {
2137     XROW_GETXXX( getArray, Reference< XArray > );
2138 }
2139 
2140 //-----------------------------------------------------------------
2141 // Type Converter Support
2142 //-----------------------------------------------------------------
2143 
2144 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2145 {
2146     osl::Guard< osl::Mutex > aGuard( m_aMutex );
2147 
2148     if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2149     {
2150         m_bTriedToGetTypeConverter = sal_True;
2151         m_xTypeConverter = Reference< XTypeConverter >(
2152                                 m_xSMgr->createInstance(
2153                                     OUString::createFromAscii(
2154                                         "com.sun.star.script.Converter" ) ),
2155                                 UNO_QUERY );
2156 
2157         OSL_ENSURE( m_xTypeConverter.is(),
2158                     "PropertyValueSet::getTypeConverter() - "
2159                     "Service 'com.sun.star.script.Converter' n/a!" );
2160     }
2161     return m_xTypeConverter;
2162 }
2163 
2164 //--------------------------------------------------------------------------
2165 //--------------------------------------------------------------------------
2166 // class CachedContentResultSetFactory
2167 //--------------------------------------------------------------------------
2168 //--------------------------------------------------------------------------
2169 
2170 CachedContentResultSetFactory::CachedContentResultSetFactory(
2171         const Reference< XMultiServiceFactory > & rSMgr )
2172 {
2173     m_xSMgr = rSMgr;
2174 }
2175 
2176 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2177 {
2178 }
2179 
2180 //--------------------------------------------------------------------------
2181 // CachedContentResultSetFactory XInterface methods.
2182 //--------------------------------------------------------------------------
2183 
2184 XINTERFACE_IMPL_3( CachedContentResultSetFactory,
2185                    XTypeProvider,
2186                    XServiceInfo,
2187                    XCachedContentResultSetFactory );
2188 
2189 //--------------------------------------------------------------------------
2190 // CachedContentResultSetFactory XTypeProvider methods.
2191 //--------------------------------------------------------------------------
2192 
2193 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2194                       XTypeProvider,
2195                       XServiceInfo,
2196                       XCachedContentResultSetFactory );
2197 
2198 //--------------------------------------------------------------------------
2199 // CachedContentResultSetFactory XServiceInfo methods.
2200 //--------------------------------------------------------------------------
2201 
2202 XSERVICEINFO_IMPL_1( CachedContentResultSetFactory,
2203                      OUString::createFromAscii(
2204                         "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2205                      OUString::createFromAscii(
2206                         CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2207 
2208 //--------------------------------------------------------------------------
2209 // Service factory implementation.
2210 //--------------------------------------------------------------------------
2211 
2212 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2213 
2214 //--------------------------------------------------------------------------
2215 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2216 //--------------------------------------------------------------------------
2217 
2218     //virtual
2219 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
2220     ::createCachedContentResultSet(
2221             const Reference< XResultSet > & xSource,
2222             const Reference< XContentIdentifierMapping > & xMapping )
2223             throw( com::sun::star::uno::RuntimeException )
2224 {
2225     Reference< XResultSet > xRet;
2226     xRet = new CachedContentResultSet( m_xSMgr, xSource, xMapping );
2227     return xRet;
2228 }
2229 
2230