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