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