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