Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / cacher / cachedcontentresultsetstub.cxx
blobbf4651f7969471b3983b6d134799fe2a3b94bbf5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "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>
27 #include <ucbhelper/macros.hxx>
29 using namespace com::sun::star::beans;
30 using namespace com::sun::star::lang;
31 using namespace com::sun::star::sdbc;
32 using namespace com::sun::star::ucb;
33 using namespace com::sun::star::uno;
34 using namespace com::sun::star::util;
35 using namespace cppu;
38 CachedContentResultSetStub::CachedContentResultSetStub( Reference< XResultSet > const & xOrigin )
39 : ContentResultSetWrapper( xOrigin )
40 , m_nColumnCount( 0 )
41 , m_bColumnCountCached( false )
42 , m_bNeedToPropagateFetchSize( true )
43 , m_bFirstFetchSizePropagationDone( false )
44 , m_nLastFetchSize( 1 )//this value is not important at all
45 , m_bLastFetchDirection( true )//this value is not important at all
46 , m_aPropertyNameForFetchSize( OUString("FetchSize") )
47 , m_aPropertyNameForFetchDirection( OUString("FetchDirection") )
49 impl_init();
52 CachedContentResultSetStub::~CachedContentResultSetStub()
54 impl_deinit();
58 // XInterface methods.
59 void SAL_CALL CachedContentResultSetStub::acquire()
60 throw()
62 OWeakObject::acquire();
65 void SAL_CALL CachedContentResultSetStub::release()
66 throw()
68 OWeakObject::release();
71 Any SAL_CALL CachedContentResultSetStub
72 ::queryInterface( const Type& rType )
74 //list all interfaces inclusive baseclasses of interfaces
76 Any aRet = ContentResultSetWrapper::queryInterface( rType );
77 if( aRet.hasValue() )
78 return aRet;
80 aRet = cppu::queryInterface( rType
81 , static_cast< XTypeProvider* >( this )
82 , static_cast< XServiceInfo* >( this )
83 , static_cast< XFetchProvider* >( this )
84 , static_cast< XFetchProviderForContentAccess* >( this )
87 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
91 // own methods. ( inherited )
94 //virtual
95 void CachedContentResultSetStub
96 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
98 impl_EnsureNotDisposed();
100 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
101 //because it will ignore them anyway and we can save this remote calls
102 if( rEvt.PropertyName == m_aPropertyNameForFetchSize
103 || rEvt.PropertyName == m_aPropertyNameForFetchDirection )
104 return;
106 PropertyChangeEvent aEvt( rEvt );
107 aEvt.Source = static_cast< XPropertySet * >( this );
108 aEvt.Further = false;
110 impl_notifyPropertyChangeListeners( aEvt );
114 //virtual
115 void CachedContentResultSetStub
116 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
118 impl_EnsureNotDisposed();
120 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
121 //because it will ignore them anyway and we can save this remote calls
122 if( rEvt.PropertyName == m_aPropertyNameForFetchSize
123 || rEvt.PropertyName == m_aPropertyNameForFetchDirection )
124 return;
126 PropertyChangeEvent aEvt( rEvt );
127 aEvt.Source = static_cast< XPropertySet * >( this );
128 aEvt.Further = false;
130 impl_notifyVetoableChangeListeners( aEvt );
134 // XTypeProvider methods.
137 XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub )
138 //list all interfaces exclusive baseclasses
139 Sequence< Type > SAL_CALL CachedContentResultSetStub
140 ::getTypes()
142 static Sequence<Type> ourTypes(
143 { CPPU_TYPE_REF( XTypeProvider ),
144 CPPU_TYPE_REF( XServiceInfo ),
145 CPPU_TYPE_REF( XComponent ),
146 CPPU_TYPE_REF( XCloseable ),
147 CPPU_TYPE_REF( XResultSetMetaDataSupplier ),
148 CPPU_TYPE_REF( XPropertySet ),
149 CPPU_TYPE_REF( XPropertyChangeListener ),
150 CPPU_TYPE_REF( XVetoableChangeListener ),
151 CPPU_TYPE_REF( XResultSet ),
152 CPPU_TYPE_REF( XContentAccess ),
153 CPPU_TYPE_REF( XRow ),
154 CPPU_TYPE_REF( XFetchProvider ),
155 CPPU_TYPE_REF( XFetchProviderForContentAccess ) } );
157 return ourTypes;
161 // XServiceInfo methods.
163 OUString SAL_CALL CachedContentResultSetStub::getImplementationName()
165 return "com.sun.star.comp.ucb.CachedContentResultSetStub";
168 sal_Bool SAL_CALL CachedContentResultSetStub::supportsService( const OUString& ServiceName )
170 return cppu::supportsService( this, ServiceName );
173 css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetStub::getSupportedServiceNames()
175 return { CACHED_CRS_STUB_SERVICE_NAME };
180 // XFetchProvider methods.
183 FetchResult CachedContentResultSetStub::impl_fetchHelper(
184 sal_Int32 nRowStartPosition, sal_Int32 nRowCount, bool bDirection,
185 std::function<void( css::uno::Any& rRowContent)> impl_loadRow)
187 impl_EnsureNotDisposed();
188 if( !m_xResultSetOrigin.is() )
190 OSL_FAIL( "broadcaster was disposed already" );
191 throw RuntimeException();
193 impl_propagateFetchSizeAndDirection( nRowCount, bDirection );
194 FetchResult aRet;
195 aRet.StartIndex = nRowStartPosition;
196 aRet.Orientation = bDirection;
197 aRet.FetchError = FetchError::SUCCESS; /*ENDOFDATA, EXCEPTION*/
198 sal_Int32 nOldOriginal_Pos = m_xResultSetOrigin->getRow();
199 if( impl_isForwardOnly() )
201 if( nOldOriginal_Pos != nRowStartPosition )
203 /*@todo*/
204 aRet.FetchError = FetchError::EXCEPTION;
205 return aRet;
207 if( nRowCount != 1 )
208 aRet.FetchError = FetchError::EXCEPTION;
210 aRet.Rows.realloc( 1 );
214 impl_loadRow( aRet.Rows[0] );
216 catch( SQLException& )
218 aRet.Rows.realloc( 0 );
219 aRet.FetchError = FetchError::EXCEPTION;
220 return aRet;
222 return aRet;
224 aRet.Rows.realloc( nRowCount );
225 bool bOldOriginal_AfterLast = false;
226 if( !nOldOriginal_Pos )
227 bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast();
228 sal_Int32 nN = 1;
229 bool bValidNewPos = false;
234 /*if( nOldOriginal_Pos != nRowStartPosition )*/
235 bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition );
237 catch( SQLException& )
239 aRet.Rows.realloc( 0 );
240 aRet.FetchError = FetchError::EXCEPTION;
241 return aRet;
243 if( !bValidNewPos )
245 aRet.Rows.realloc( 0 );
246 aRet.FetchError = FetchError::EXCEPTION;
248 /*restore old position*/
249 if( nOldOriginal_Pos )
250 m_xResultSetOrigin->absolute( nOldOriginal_Pos );
251 else if( bOldOriginal_AfterLast )
252 m_xResultSetOrigin->afterLast();
253 else
254 m_xResultSetOrigin->beforeFirst();
256 return aRet;
258 for( ; nN <= nRowCount; )
260 impl_loadRow( aRet.Rows[nN-1] );
261 nN++;
262 if( nN <= nRowCount )
264 if( bDirection )
266 if( !m_xResultSetOrigin->next() )
268 aRet.Rows.realloc( nN-1 );
269 aRet.FetchError = FetchError::ENDOFDATA;
270 break;
273 else
275 if( !m_xResultSetOrigin->previous() )
277 aRet.Rows.realloc( nN-1 );
278 aRet.FetchError = FetchError::ENDOFDATA;
279 break;
285 catch( SQLException& )
287 aRet.Rows.realloc( nN-1 );
288 aRet.FetchError = FetchError::EXCEPTION;
290 /*restore old position*/
291 if( nOldOriginal_Pos )
292 m_xResultSetOrigin->absolute( nOldOriginal_Pos );
293 else if( bOldOriginal_AfterLast )
294 m_xResultSetOrigin->afterLast();
295 else
296 m_xResultSetOrigin->beforeFirst();
297 return aRet;
300 FetchResult SAL_CALL CachedContentResultSetStub
301 ::fetch( sal_Int32 nRowStartPosition
302 , sal_Int32 nRowCount, sal_Bool bDirection )
304 impl_init_xRowOrigin();
305 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
306 [&](css::uno::Any& rRowContent)
307 { return impl_getCurrentRowContent(rRowContent, m_xRowOrigin); });
310 sal_Int32 CachedContentResultSetStub
311 ::impl_getColumnCount()
313 sal_Int32 nCount;
314 bool bCached;
316 osl::Guard< osl::Mutex > aGuard( m_aMutex );
317 nCount = m_nColumnCount;
318 bCached = m_bColumnCountCached;
320 if( !bCached )
324 Reference< XResultSetMetaData > xMetaData = getMetaData();
325 if( xMetaData.is() )
326 nCount = xMetaData->getColumnCount();
328 catch( SQLException& )
330 OSL_FAIL( "couldn't determine the column count" );
331 nCount = 0;
334 osl::Guard< osl::Mutex > aGuard( m_aMutex );
335 m_nColumnCount = nCount;
336 m_bColumnCountCached = true;
337 return m_nColumnCount;
340 void CachedContentResultSetStub
341 ::impl_getCurrentRowContent( Any& rRowContent
342 , const Reference< XRow >& xRow )
344 sal_Int32 nCount = impl_getColumnCount();
346 Sequence< Any > aContent( nCount );
347 for( sal_Int32 nN = 1; nN <= nCount; nN++ )
349 aContent[nN-1] = xRow->getObject( nN, nullptr );
352 rRowContent <<= aContent;
355 void CachedContentResultSetStub
356 ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, bool bFetchDirection )
358 //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResultSets
360 //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls
362 //if the underlying ResultSet has a property FetchSize and FetchDirection,
363 //we will set these properties, if the new given parameters are different from the last ones
365 if( !m_bNeedToPropagateFetchSize )
366 return;
368 bool bNeedAction;
369 sal_Int32 nLastSize;
370 bool bLastDirection;
371 bool bFirstPropagationDone;
373 osl::Guard< osl::Mutex > aGuard( m_aMutex );
374 bNeedAction = m_bNeedToPropagateFetchSize;
375 nLastSize = m_nLastFetchSize;
376 bLastDirection = m_bLastFetchDirection;
377 bFirstPropagationDone = m_bFirstFetchSizePropagationDone;
379 if( bNeedAction )
381 if( nLastSize == nFetchSize
382 && bLastDirection == bFetchDirection
383 && bFirstPropagationDone )
384 return;
386 if(!bFirstPropagationDone)
388 //check whether the properties 'FetchSize' and 'FetchDirection' do exist
390 Reference< XPropertySetInfo > xPropertySetInfo = getPropertySetInfo();
391 bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize );
392 bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection );
394 if(!bHasSize || !bHasDirection)
396 osl::Guard< osl::Mutex > aGuard( m_aMutex );
397 m_bNeedToPropagateFetchSize = false;
398 return;
402 bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone;
403 bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone;
406 osl::Guard< osl::Mutex > aGuard( m_aMutex );
407 m_bFirstFetchSizePropagationDone = true;
408 m_nLastFetchSize = nFetchSize;
409 m_bLastFetchDirection = bFetchDirection;
412 if( bSetSize )
414 Any aValue;
415 aValue <<= nFetchSize;
418 setPropertyValue( m_aPropertyNameForFetchSize, aValue );
420 catch( css::uno::Exception& ) {}
422 if( bSetDirection )
424 sal_Int32 nFetchDirection = FetchDirection::FORWARD;
425 if( !bFetchDirection )
426 nFetchDirection = FetchDirection::REVERSE;
427 Any aValue;
428 aValue <<= nFetchDirection;
431 setPropertyValue( m_aPropertyNameForFetchDirection, aValue );
433 catch( css::uno::Exception& ) {}
440 // XFetchProviderForContentAccess methods.
443 void CachedContentResultSetStub
444 ::impl_getCurrentContentIdentifierString( Any& rAny
445 , const Reference< XContentAccess >& xContentAccess )
447 rAny <<= xContentAccess->queryContentIdentifierString();
450 void CachedContentResultSetStub
451 ::impl_getCurrentContentIdentifier( Any& rAny
452 , const Reference< XContentAccess >& xContentAccess )
454 rAny <<= xContentAccess->queryContentIdentifier();
457 void CachedContentResultSetStub
458 ::impl_getCurrentContent( Any& rAny
459 , const Reference< XContentAccess >& xContentAccess )
461 rAny <<= xContentAccess->queryContent();
464 //virtual
465 FetchResult SAL_CALL CachedContentResultSetStub
466 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
467 , sal_Int32 nRowCount, sal_Bool bDirection )
469 impl_init_xContentAccessOrigin();
470 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
471 [&](css::uno::Any& rRowContent)
472 { return impl_getCurrentContentIdentifierString(rRowContent, m_xContentAccessOrigin); });
475 //virtual
476 FetchResult SAL_CALL CachedContentResultSetStub
477 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
478 , sal_Int32 nRowCount, sal_Bool bDirection )
480 impl_init_xContentAccessOrigin();
481 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
482 [&](css::uno::Any& rRowContent)
483 { return impl_getCurrentContentIdentifier(rRowContent, m_xContentAccessOrigin); });
486 //virtual
487 FetchResult SAL_CALL CachedContentResultSetStub
488 ::fetchContents( sal_Int32 nRowStartPosition
489 , sal_Int32 nRowCount, sal_Bool bDirection )
491 impl_init_xContentAccessOrigin();
492 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
493 [&](css::uno::Any& rRowContent)
494 { return impl_getCurrentContent(rRowContent, m_xContentAccessOrigin); });
498 // class CachedContentResultSetStubFactory
501 CachedContentResultSetStubFactory::CachedContentResultSetStubFactory()
505 CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory()
510 // CachedContentResultSetStubFactory XServiceInfo methods.
512 XSERVICEINFO_COMMOM_IMPL( CachedContentResultSetStubFactory,
513 "com.sun.star.comp.ucb.CachedContentResultSetStubFactory" )
514 /// @throws css::uno::Exception
515 static css::uno::Reference< css::uno::XInterface >
516 CachedContentResultSetStubFactory_CreateInstance( const css::uno::Reference< css::lang::XMultiServiceFactory> & )
518 css::lang::XServiceInfo* pX = new CachedContentResultSetStubFactory;
519 return css::uno::Reference< css::uno::XInterface >::query( pX );
521 css::uno::Sequence< OUString >
522 CachedContentResultSetStubFactory::getSupportedServiceNames_Static()
524 return { CACHED_CRS_STUB_FACTORY_NAME };
527 // Service factory implementation.
530 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetStubFactory );
533 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
536 //virtual
537 Reference< XResultSet > SAL_CALL CachedContentResultSetStubFactory
538 ::createCachedContentResultSetStub(
539 const Reference< XResultSet > & xSource )
541 if( xSource.is() )
543 Reference< XResultSet > xRet = new CachedContentResultSetStub( xSource );
544 return xRet;
546 return nullptr;
550 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */