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