1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "cachedcontentresultsetstub.hxx"
22 #include <com/sun/star/sdbc/FetchDirection.hpp>
23 #include <com/sun/star/sdbc/SQLException.hpp>
24 #include <com/sun/star/ucb/FetchError.hpp>
25 #include <osl/diagnose.h>
26 #include <cppuhelper/queryinterface.hxx>
28 using namespace com::sun::star::beans
;
29 using namespace com::sun::star::lang
;
30 using namespace com::sun::star::sdbc
;
31 using namespace com::sun::star::ucb
;
32 using namespace com::sun::star::uno
;
33 using namespace com::sun::star::util
;
37 CachedContentResultSetStub::CachedContentResultSetStub( Reference
< XResultSet
> const & xOrigin
)
38 : ContentResultSetWrapper( xOrigin
)
40 , m_bColumnCountCached( false )
41 , m_bNeedToPropagateFetchSize( true )
42 , m_bFirstFetchSizePropagationDone( false )
43 , m_nLastFetchSize( 1 )//this value is not important at all
44 , m_bLastFetchDirection( true )//this value is not important at all
45 , m_aPropertyNameForFetchSize( OUString("FetchSize") )
46 , m_aPropertyNameForFetchDirection( OUString("FetchDirection") )
51 CachedContentResultSetStub::~CachedContentResultSetStub()
57 // XInterface methods.
58 void SAL_CALL
CachedContentResultSetStub::acquire()
61 OWeakObject::acquire();
64 void SAL_CALL
CachedContentResultSetStub::release()
67 OWeakObject::release();
70 Any SAL_CALL CachedContentResultSetStub
71 ::queryInterface( const Type
& rType
)
73 //list all interfaces inclusive baseclasses of interfaces
75 Any aRet
= ContentResultSetWrapper::queryInterface( rType
);
79 aRet
= cppu::queryInterface( rType
80 , static_cast< XTypeProvider
* >( this )
81 , static_cast< XServiceInfo
* >( this )
82 , static_cast< XFetchProvider
* >( this )
83 , static_cast< XFetchProviderForContentAccess
* >( this )
86 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
90 // own methods. ( inherited )
94 void CachedContentResultSetStub
95 ::impl_propertyChange( const PropertyChangeEvent
& rEvt
)
97 impl_EnsureNotDisposed();
99 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
100 //because it will ignore them anyway and we can save this remote calls
101 if( rEvt
.PropertyName
== m_aPropertyNameForFetchSize
102 || rEvt
.PropertyName
== m_aPropertyNameForFetchDirection
)
105 PropertyChangeEvent
aEvt( rEvt
);
106 aEvt
.Source
= static_cast< XPropertySet
* >( this );
107 aEvt
.Further
= false;
109 impl_notifyPropertyChangeListeners( aEvt
);
114 void CachedContentResultSetStub
115 ::impl_vetoableChange( const PropertyChangeEvent
& rEvt
)
117 impl_EnsureNotDisposed();
119 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
120 //because it will ignore them anyway and we can save this remote calls
121 if( rEvt
.PropertyName
== m_aPropertyNameForFetchSize
122 || rEvt
.PropertyName
== m_aPropertyNameForFetchDirection
)
125 PropertyChangeEvent
aEvt( rEvt
);
126 aEvt
.Source
= static_cast< XPropertySet
* >( this );
127 aEvt
.Further
= false;
129 impl_notifyVetoableChangeListeners( aEvt
);
133 // XTypeProvider methods.
136 XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub
)
137 //list all interfaces exclusive baseclasses
138 Sequence
< Type
> SAL_CALL CachedContentResultSetStub
141 static Sequence
<Type
> ourTypes(
142 { CPPU_TYPE_REF( XTypeProvider
),
143 CPPU_TYPE_REF( XServiceInfo
),
144 CPPU_TYPE_REF( XComponent
),
145 CPPU_TYPE_REF( XCloseable
),
146 CPPU_TYPE_REF( XResultSetMetaDataSupplier
),
147 CPPU_TYPE_REF( XPropertySet
),
148 CPPU_TYPE_REF( XPropertyChangeListener
),
149 CPPU_TYPE_REF( XVetoableChangeListener
),
150 CPPU_TYPE_REF( XResultSet
),
151 CPPU_TYPE_REF( XContentAccess
),
152 CPPU_TYPE_REF( XRow
),
153 CPPU_TYPE_REF( XFetchProvider
),
154 CPPU_TYPE_REF( XFetchProviderForContentAccess
) } );
160 // XServiceInfo methods.
162 OUString SAL_CALL
CachedContentResultSetStub::getImplementationName()
164 return OUString( "com.sun.star.comp.ucb.CachedContentResultSetStub" );
167 sal_Bool SAL_CALL
CachedContentResultSetStub::supportsService( const OUString
& ServiceName
)
169 return cppu::supportsService( this, ServiceName
);
172 css::uno::Sequence
< OUString
> SAL_CALL
CachedContentResultSetStub::getSupportedServiceNames()
174 return { CACHED_CRS_STUB_SERVICE_NAME
};
179 // XFetchProvider methods.
182 FetchResult
CachedContentResultSetStub::impl_fetchHelper(
183 sal_Int32 nRowStartPosition
, sal_Int32 nRowCount
, bool bDirection
,
184 std::function
<void( css::uno::Any
& rRowContent
)> impl_loadRow
)
186 impl_EnsureNotDisposed();
187 if( !m_xResultSetOrigin
.is() )
189 OSL_FAIL( "broadcaster was disposed already" );
190 throw RuntimeException();
192 impl_propagateFetchSizeAndDirection( nRowCount
, bDirection
);
194 aRet
.StartIndex
= nRowStartPosition
;
195 aRet
.Orientation
= bDirection
;
196 aRet
.FetchError
= FetchError::SUCCESS
; /*ENDOFDATA, EXCEPTION*/
197 sal_Int32 nOldOriginal_Pos
= m_xResultSetOrigin
->getRow();
198 if( impl_isForwardOnly() )
200 if( nOldOriginal_Pos
!= nRowStartPosition
)
203 aRet
.FetchError
= FetchError::EXCEPTION
;
207 aRet
.FetchError
= FetchError::EXCEPTION
;
209 aRet
.Rows
.realloc( 1 );
213 impl_loadRow( aRet
.Rows
[0] );
215 catch( SQLException
& )
217 aRet
.Rows
.realloc( 0 );
218 aRet
.FetchError
= FetchError::EXCEPTION
;
223 aRet
.Rows
.realloc( nRowCount
);
224 bool bOldOriginal_AfterLast
= false;
225 if( !nOldOriginal_Pos
)
226 bOldOriginal_AfterLast
= m_xResultSetOrigin
->isAfterLast();
228 bool bValidNewPos
= false;
233 /*if( nOldOriginal_Pos != nRowStartPosition )*/
234 bValidNewPos
= m_xResultSetOrigin
->absolute( nRowStartPosition
);
236 catch( SQLException
& )
238 aRet
.Rows
.realloc( 0 );
239 aRet
.FetchError
= FetchError::EXCEPTION
;
244 aRet
.Rows
.realloc( 0 );
245 aRet
.FetchError
= FetchError::EXCEPTION
;
247 /*restore old position*/
248 if( nOldOriginal_Pos
)
249 m_xResultSetOrigin
->absolute( nOldOriginal_Pos
);
250 else if( bOldOriginal_AfterLast
)
251 m_xResultSetOrigin
->afterLast();
253 m_xResultSetOrigin
->beforeFirst();
257 for( ; nN
<= nRowCount
; )
259 impl_loadRow( aRet
.Rows
[nN
-1] );
261 if( nN
<= nRowCount
)
265 if( !m_xResultSetOrigin
->next() )
267 aRet
.Rows
.realloc( nN
-1 );
268 aRet
.FetchError
= FetchError::ENDOFDATA
;
274 if( !m_xResultSetOrigin
->previous() )
276 aRet
.Rows
.realloc( nN
-1 );
277 aRet
.FetchError
= FetchError::ENDOFDATA
;
284 catch( SQLException
& )
286 aRet
.Rows
.realloc( nN
-1 );
287 aRet
.FetchError
= FetchError::EXCEPTION
;
289 /*restore old position*/
290 if( nOldOriginal_Pos
)
291 m_xResultSetOrigin
->absolute( nOldOriginal_Pos
);
292 else if( bOldOriginal_AfterLast
)
293 m_xResultSetOrigin
->afterLast();
295 m_xResultSetOrigin
->beforeFirst();
299 FetchResult SAL_CALL CachedContentResultSetStub
300 ::fetch( sal_Int32 nRowStartPosition
301 , sal_Int32 nRowCount
, sal_Bool bDirection
)
303 impl_init_xRowOrigin();
304 return impl_fetchHelper( nRowStartPosition
, nRowCount
, bDirection
,
305 [&](css::uno::Any
& rRowContent
)
306 { return impl_getCurrentRowContent(rRowContent
, m_xRowOrigin
); });
309 sal_Int32 CachedContentResultSetStub
310 ::impl_getColumnCount()
315 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
316 nCount
= m_nColumnCount
;
317 bCached
= m_bColumnCountCached
;
323 Reference
< XResultSetMetaData
> xMetaData
= getMetaData();
325 nCount
= xMetaData
->getColumnCount();
327 catch( SQLException
& )
329 OSL_FAIL( "couldn't determine the column count" );
333 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
334 m_nColumnCount
= nCount
;
335 m_bColumnCountCached
= true;
336 return m_nColumnCount
;
339 void CachedContentResultSetStub
340 ::impl_getCurrentRowContent( Any
& rRowContent
341 , const Reference
< XRow
>& xRow
)
343 sal_Int32 nCount
= impl_getColumnCount();
345 Sequence
< Any
> aContent( nCount
);
346 for( sal_Int32 nN
= 1; nN
<= nCount
; nN
++ )
348 aContent
[nN
-1] = xRow
->getObject( nN
, nullptr );
351 rRowContent
<<= aContent
;
354 void CachedContentResultSetStub
355 ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize
, bool bFetchDirection
)
357 //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResultSets
359 //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls
361 //if the underlying ResultSet has a property FetchSize and FetchDirection,
362 //we will set these properties, if the new given parameters are different from the last ones
364 if( !m_bNeedToPropagateFetchSize
)
370 bool bFirstPropagationDone
;
372 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
373 bNeedAction
= m_bNeedToPropagateFetchSize
;
374 nLastSize
= m_nLastFetchSize
;
375 bLastDirection
= m_bLastFetchDirection
;
376 bFirstPropagationDone
= m_bFirstFetchSizePropagationDone
;
380 if( nLastSize
== nFetchSize
381 && bLastDirection
== bFetchDirection
382 && bFirstPropagationDone
)
385 if(!bFirstPropagationDone
)
387 //check whether the properties 'FetchSize' and 'FetchDirection' do exist
389 Reference
< XPropertySetInfo
> xPropertySetInfo
= getPropertySetInfo();
390 bool bHasSize
= xPropertySetInfo
->hasPropertyByName( m_aPropertyNameForFetchSize
);
391 bool bHasDirection
= xPropertySetInfo
->hasPropertyByName( m_aPropertyNameForFetchDirection
);
393 if(!bHasSize
|| !bHasDirection
)
395 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
396 m_bNeedToPropagateFetchSize
= false;
401 bool bSetSize
= ( nLastSize
!=nFetchSize
) || !bFirstPropagationDone
;
402 bool bSetDirection
= ( bLastDirection
!=bFetchDirection
) || !bFirstPropagationDone
;
405 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
406 m_bFirstFetchSizePropagationDone
= true;
407 m_nLastFetchSize
= nFetchSize
;
408 m_bLastFetchDirection
= bFetchDirection
;
414 aValue
<<= nFetchSize
;
417 setPropertyValue( m_aPropertyNameForFetchSize
, aValue
);
419 catch( css::uno::Exception
& ) {}
423 sal_Int32 nFetchDirection
= FetchDirection::FORWARD
;
424 if( !bFetchDirection
)
425 nFetchDirection
= FetchDirection::REVERSE
;
427 aValue
<<= nFetchDirection
;
430 setPropertyValue( m_aPropertyNameForFetchDirection
, aValue
);
432 catch( css::uno::Exception
& ) {}
439 // XFetchProviderForContentAccess methods.
442 void CachedContentResultSetStub
443 ::impl_getCurrentContentIdentifierString( Any
& rAny
444 , const Reference
< XContentAccess
>& xContentAccess
)
446 rAny
<<= xContentAccess
->queryContentIdentifierString();
449 void CachedContentResultSetStub
450 ::impl_getCurrentContentIdentifier( Any
& rAny
451 , const Reference
< XContentAccess
>& xContentAccess
)
453 rAny
<<= xContentAccess
->queryContentIdentifier();
456 void CachedContentResultSetStub
457 ::impl_getCurrentContent( Any
& rAny
458 , const Reference
< XContentAccess
>& xContentAccess
)
460 rAny
<<= xContentAccess
->queryContent();
464 FetchResult SAL_CALL CachedContentResultSetStub
465 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
466 , sal_Int32 nRowCount
, sal_Bool bDirection
)
468 impl_init_xContentAccessOrigin();
469 return impl_fetchHelper( nRowStartPosition
, nRowCount
, bDirection
,
470 [&](css::uno::Any
& rRowContent
)
471 { return impl_getCurrentContentIdentifierString(rRowContent
, m_xContentAccessOrigin
); });
475 FetchResult SAL_CALL CachedContentResultSetStub
476 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
477 , sal_Int32 nRowCount
, sal_Bool bDirection
)
479 impl_init_xContentAccessOrigin();
480 return impl_fetchHelper( nRowStartPosition
, nRowCount
, bDirection
,
481 [&](css::uno::Any
& rRowContent
)
482 { return impl_getCurrentContentIdentifier(rRowContent
, m_xContentAccessOrigin
); });
486 FetchResult SAL_CALL CachedContentResultSetStub
487 ::fetchContents( sal_Int32 nRowStartPosition
488 , sal_Int32 nRowCount
, sal_Bool bDirection
)
490 impl_init_xContentAccessOrigin();
491 return impl_fetchHelper( nRowStartPosition
, nRowCount
, bDirection
,
492 [&](css::uno::Any
& rRowContent
)
493 { return impl_getCurrentContent(rRowContent
, m_xContentAccessOrigin
); });
497 // class CachedContentResultSetStubFactory
500 CachedContentResultSetStubFactory::CachedContentResultSetStubFactory(
501 const Reference
< XMultiServiceFactory
> & rSMgr
)
506 CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory()
511 // CachedContentResultSetStubFactory XInterface methods.
512 void SAL_CALL
CachedContentResultSetStubFactory::acquire()
515 OWeakObject::acquire();
518 void SAL_CALL
CachedContentResultSetStubFactory::release()
521 OWeakObject::release();
524 css::uno::Any SAL_CALL
CachedContentResultSetStubFactory::queryInterface( const css::uno::Type
& rType
)
526 css::uno::Any aRet
= cppu::queryInterface( rType
,
527 static_cast< XTypeProvider
* >(this),
528 static_cast< XServiceInfo
* >(this),
529 static_cast< XCachedContentResultSetStubFactory
* >(this)
531 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
534 // CachedContentResultSetStubFactory XTypeProvider methods.
537 XTYPEPROVIDER_IMPL_3( CachedContentResultSetStubFactory
,
540 XCachedContentResultSetStubFactory
);
543 // CachedContentResultSetStubFactory XServiceInfo methods.
545 XSERVICEINFO_COMMOM_IMPL( CachedContentResultSetStubFactory
,
546 OUString( "com.sun.star.comp.ucb.CachedContentResultSetStubFactory" ) )
547 /// @throws css::uno::Exception
548 static css::uno::Reference
< css::uno::XInterface
>
549 CachedContentResultSetStubFactory_CreateInstance( const css::uno::Reference
< css::lang::XMultiServiceFactory
> & rSMgr
)
551 css::lang::XServiceInfo
* pX
=
552 static_cast<css::lang::XServiceInfo
*>(new CachedContentResultSetStubFactory( rSMgr
));
553 return css::uno::Reference
< css::uno::XInterface
>::query( pX
);
555 css::uno::Sequence
< OUString
>
556 CachedContentResultSetStubFactory::getSupportedServiceNames_Static()
558 return { CACHED_CRS_STUB_FACTORY_NAME
};
561 // Service factory implementation.
564 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetStubFactory
);
567 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
571 Reference
< XResultSet
> SAL_CALL CachedContentResultSetStubFactory
572 ::createCachedContentResultSetStub(
573 const Reference
< XResultSet
> & xSource
)
577 Reference
< XResultSet
> xRet
;
578 xRet
= new CachedContentResultSetStub( xSource
);
585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */