LibreOffice Module ucb (master)  1
sortdynres.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 #include <vector>
21 #include "sortdynres.hxx"
24 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/ServiceNotFoundException.hpp>
27 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
28 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
29 #include <com/sun/star/ucb/XSourceInitialization.hpp>
31 
32 using namespace com::sun::star::beans;
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::sdbc;
35 using namespace com::sun::star::ucb;
36 using namespace com::sun::star::uno;
37 using namespace comphelper;
38 
39 
40 // The mutex to synchronize access to containers.
41 static osl::Mutex& getContainerMutex()
42 {
43  static osl::Mutex ourMutex;
44 
45  return ourMutex;
46 }
47 
48 
49 // SortedDynamicResultSet
50 
52  const Reference < XDynamicResultSet > &xOriginal,
53  const Sequence < NumberedSortingInfo > &aOptions,
54  const Reference < XAnyCompareFactory > &xCompFac,
55  const Reference < XComponentContext > &rxContext )
56 {
57  mpDisposeEventListeners = nullptr;
58  mxOwnListener = new SortedDynamicResultSetListener( this );
59 
60  mxOriginal = xOriginal;
61  maOptions = aOptions;
62  mxCompFac = xCompFac;
63  m_xContext = rxContext;
64 
65  mbGotWelcome = false;
66  mbUseOne = true;
67  mbStatic = false;
68 }
69 
70 
72 {
73  mxOwnListener->impl_OwnerDies();
74  mxOwnListener.clear();
75 
76  mpDisposeEventListeners.reset();
77 
78  mxOne.clear();
79  mxTwo.clear();
80  mxOriginal.clear();
81 }
82 
83 // XServiceInfo methods.
84 
86 {
87  return "com.sun.star.comp.ucb.SortedDynamicResultSet";
88 }
89 
90 sal_Bool SAL_CALL SortedDynamicResultSet::supportsService( const OUString& ServiceName )
91 {
92  return cppu::supportsService( this, ServiceName );
93 }
94 
95 css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSet::getSupportedServiceNames()
96 {
98 }
99 
100 // XComponent methods.
101 
103 {
104  osl::Guard< osl::Mutex > aGuard( maMutex );
105 
106  if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() )
107  {
108  EventObject aEvt;
109  aEvt.Source = static_cast< XComponent * >( this );
110  mpDisposeEventListeners->disposeAndClear( aEvt );
111  }
112 
113  mxOne.clear();
114  mxTwo.clear();
115  mxOriginal.clear();
116 
117  mbUseOne = true;
118 }
119 
121  const Reference< XEventListener >& Listener )
122 {
123  osl::Guard< osl::Mutex > aGuard( maMutex );
124 
125  if ( !mpDisposeEventListeners )
126  mpDisposeEventListeners.reset(
128 
129  mpDisposeEventListeners->addInterface( Listener );
130 }
131 
133  const Reference< XEventListener >& Listener )
134 {
135  osl::Guard< osl::Mutex > aGuard( maMutex );
136 
137  if ( mpDisposeEventListeners )
138  mpDisposeEventListeners->removeInterface( Listener );
139 }
140 
141 
142 // XDynamicResultSet methods.
143 
146 {
147  osl::Guard< osl::Mutex > aGuard( maMutex );
148 
149  if ( mxListener.is() )
150  throw ListenerAlreadySetException();
151 
152  mbStatic = true;
153 
154  if ( mxOriginal.is() )
155  {
156  mxOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
157  mxOne->Initialize( maOptions, mxCompFac );
158  }
159 
160  return mxOne.get();
161 }
162 
163 
164 void SAL_CALL
166 {
167  osl::Guard< osl::Mutex > aGuard( maMutex );
168 
169  if ( mxListener.is() )
170  throw ListenerAlreadySetException();
171 
172  addEventListener( Reference< XEventListener >::query( Listener ) );
173 
174  mxListener = Listener;
175 
176  if ( mxOriginal.is() )
177  mxOriginal->setListener( mxOwnListener.get() );
178 }
179 
180 
181 void SAL_CALL
183 {
184  if( mxListener.is() )
185  throw ListenerAlreadySetException();
186 
187  if( mbStatic )
188  throw ListenerAlreadySetException();
189 
190  Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
191  if( xTarget.is() && m_xContext.is() )
192  {
194  try
195  {
196  xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
197  }
198  catch ( Exception const & )
199  {
200  }
201 
202  if( xStubFactory.is() )
203  {
204  xStubFactory->connectToCache(
205  this, xCache, Sequence< NumberedSortingInfo > (), nullptr );
206  return;
207  }
208  }
209  throw ServiceNotFoundException();
210 }
211 
212 
214 {
215  osl::Guard< osl::Mutex > aGuard( maMutex );
216 
217  sal_Int16 nCaps = 0;
218 
219  if ( mxOriginal.is() )
220  nCaps = mxOriginal->getCapabilities();
221 
222  nCaps |= ContentResultSetCapability::SORTED;
223 
224  return nCaps;
225 }
226 
227 
228 // XDynamicResultSetListener methods.
229 
230 
246 void SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
247 {
248  osl::Guard< osl::Mutex > aGuard( maMutex );
249 
250  bool bHasNew = false;
251  bool bHasModified = false;
252 
253  SortedResultSet *pCurSet = nullptr;
254 
255  // exchange mxNew and mxOld and immediately afterwards copy the tables
256  // from Old to New
257  if ( mbGotWelcome )
258  {
259  if ( mbUseOne )
260  {
261  mbUseOne = false;
262  mxTwo->CopyData( mxOne.get() );
263  pCurSet = mxTwo.get();
264  }
265  else
266  {
267  mbUseOne = true;
268  mxOne->CopyData( mxTwo.get() );
269  pCurSet = mxOne.get();
270  }
271  }
272 
273  if (!pCurSet)
274  return;
275 
276  Any aRet;
277 
278  try {
279  aRet = pCurSet->getPropertyValue("IsRowCountFinal");
280  }
281  catch (const UnknownPropertyException&) {}
282  catch (const WrappedTargetException&) {}
283 
284  long nOldCount = pCurSet->GetCount();
285  bool bWasFinal = false;
286 
287  aRet >>= bWasFinal;
288 
289  // handle the actions in the list
290  for ( const ListAction& aAction : Changes.Changes )
291  {
292  switch ( aAction.ListActionType )
293  {
294  case ListActionType::WELCOME:
295  {
296  WelcomeDynamicResultSetStruct aWelcome;
297  if ( aAction.ActionInfo >>= aWelcome )
298  {
299  mxTwo = new SortedResultSet( aWelcome.Old );
300  mxOne = new SortedResultSet( aWelcome.New );
301  mxOne->Initialize( maOptions, mxCompFac );
302  mbGotWelcome = true;
303  mbUseOne = true;
304  pCurSet = mxOne.get();
305 
306  aWelcome.Old = mxTwo.get();
307  aWelcome.New = mxOne.get();
308 
309  std::unique_ptr<ListAction> pWelcomeAction(new ListAction);
310  pWelcomeAction->ActionInfo <<= aWelcome;
311  pWelcomeAction->Position = 0;
312  pWelcomeAction->Count = 0;
313  pWelcomeAction->ListActionType = ListActionType::WELCOME;
314 
315  maActions.Insert( std::move(pWelcomeAction) );
316  }
317  else
318  {
319  // throw RuntimeException();
320  }
321  break;
322  }
323  case ListActionType::INSERTED:
324  {
325  pCurSet->InsertNew( aAction.Position, aAction.Count );
326  bHasNew = true;
327  break;
328  }
329  case ListActionType::REMOVED:
330  {
331  pCurSet->Remove( aAction.Position,
332  aAction.Count,
333  &maActions );
334  break;
335  }
336  case ListActionType::MOVED:
337  {
338  long nOffset = 0;
339  if ( aAction.ActionInfo >>= nOffset )
340  {
341  pCurSet->Move( aAction.Position,
342  aAction.Count,
343  nOffset );
344  }
345  break;
346  }
347  case ListActionType::PROPERTIES_CHANGED:
348  {
349  pCurSet->SetChanged( aAction.Position, aAction.Count );
350  bHasModified = true;
351  break;
352  }
353  default: break;
354  }
355  }
356 
357  if ( bHasModified )
358  pCurSet->ResortModified( &maActions );
359 
360  if ( bHasNew )
361  pCurSet->ResortNew( &maActions );
362 
363  // send the new actions with a notify to the listeners
364  SendNotify();
365 
366  // check for propertyChangeEvents
367  pCurSet->CheckProperties( nOldCount, bWasFinal );
368 }
369 
370 // XEventListener
371 
373 {
374  mxListener.clear();
375  mxOriginal.clear();
376 }
377 
378 // private methods
379 
381 {
382  sal_Int32 nCount = maActions.Count();
383 
384  if ( nCount && mxListener.is() )
385  {
386  Sequence< ListAction > aActionList( maActions.Count() );
387  ListAction *pActionList = aActionList.getArray();
388 
389  for ( sal_Int32 i=0; i<nCount; i++ )
390  {
391  pActionList[ i ] = *(maActions.GetAction( i ));
392  }
393 
394  ListEvent aNewEvent;
395  aNewEvent.Changes = aActionList;
396 
397  mxListener->notify( aNewEvent );
398  }
399 
400  // clean up
401  maActions.Clear();
402 }
403 
404 // SortedDynamicResultSetFactory
405 
407  const Reference< XComponentContext > & rxContext )
408 {
409  m_xContext = rxContext;
410 }
411 
412 
414 {
415 }
416 
417 
418 // XServiceInfo methods.
419 
421 {
422  return getImplementationName_Static();
423 }
424 
426 {
427  return "com.sun.star.comp.ucb.SortedDynamicResultSetFactory";
428 }
429 
430 sal_Bool SAL_CALL SortedDynamicResultSetFactory::supportsService( const OUString& ServiceName )
431 {
432  return cppu::supportsService( this, ServiceName );
433 }
434 
435 css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSetFactory::getSupportedServiceNames()
436 {
437  return getSupportedServiceNames_Static();
438 }
439 
441 static css::uno::Reference< css::uno::XInterface >
443  css::lang::XMultiServiceFactory> & rSMgr )
444 {
445  return static_cast<css::lang::XServiceInfo*>(
447 }
448 
450 {
451  css::uno::Sequence<OUString> aSNS { DYNAMIC_RESULTSET_FACTORY_NAME };
452  return aSNS;
453 }
454 
455 
456 // Service factory implementation.
457 css::uno::Reference< css::lang::XSingleServiceFactory >
458 SortedDynamicResultSetFactory::createServiceFactory( const css::uno::Reference< css::lang::XMultiServiceFactory >& rxServiceMgr )
459 {
461  rxServiceMgr,
465 }
466 
467 // SortedDynamicResultSetFactory methods.
468 
471  const Reference< XDynamicResultSet > & Source,
472  const Sequence< NumberedSortingInfo > & Info,
473  const Reference< XAnyCompareFactory > & CompareFactory )
474 {
475  Reference< XDynamicResultSet > xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, m_xContext );
476  return xRet;
477 }
478 
479 // EventList
480 
482 {
483  maData.clear();
484 }
485 
486 void EventList::AddEvent( sal_IntPtr nType, sal_IntPtr nPos )
487 {
488  std::unique_ptr<ListAction> pAction(new ListAction);
489  pAction->Position = nPos;
490  pAction->Count = 1;
491  pAction->ListActionType = nType;
492 
493  Insert( std::move(pAction) );
494 }
495 
496 // SortedDynamicResultSetListener
497 
499  SortedDynamicResultSet *mOwner )
500 {
501  mpOwner = mOwner;
502 }
503 
504 
506 {
507 }
508 
509 // XEventListener ( base of XDynamicResultSetListener )
510 
511 void SAL_CALL
512 SortedDynamicResultSetListener::disposing( const EventObject& /*Source*/ )
513 {
514  osl::Guard< osl::Mutex > aGuard( maMutex );
515 
516  if ( mpOwner )
517  mpOwner->impl_disposing();
518 }
519 
520 
521 // XDynamicResultSetListener
522 
523 void SAL_CALL
524 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
525 {
526  osl::Guard< osl::Mutex > aGuard( maMutex );
527 
528  if ( mpOwner )
529  mpOwner->impl_notify( Changes );
530 }
531 
532 // own methods:
533 
534 void
536 {
537  osl::Guard< osl::Mutex > aGuard( maMutex );
538  mpOwner = nullptr;
539 }
540 
541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
xdictionarydata maData
::osl::Mutex maMutex
void ResortModified(EventList *pList)
static css::uno::Sequence< OUString > getSupportedServiceNames_Static()
Definition: sortdynres.cxx:449
void Remove(sal_IntPtr nPos, sal_IntPtr nCount, EventList *pList)
#define DYNAMIC_RESULTSET_SERVICE_NAME
Definition: sortdynres.hxx:39
void impl_notify(const css::ucb::ListEvent &Changes)
In the first notify-call the listener gets the two XResultSets and has to hold them...
Definition: sortdynres.cxx:246
UCBHELPER_DLLPUBLIC css::uno::Reference< css::uno::XComponentContext > getComponentContext(css::uno::Reference< css::lang::XMultiServiceFactory > const &factory)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: sortdynres.cxx:430
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void CopyData(SortedResultSet *pSource)
virtual ~SortedDynamicResultSetListener() override
Definition: sortdynres.cxx:505
void AddEvent(sal_IntPtr nType, sal_IntPtr nPos)
Definition: sortdynres.cxx:486
virtual ~SortedDynamicResultSet() override
Definition: sortdynres.cxx:71
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getStaticResultSet() override
Definition: sortdynres.cxx:145
void Clear()
Definition: sortdynres.cxx:481
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &Listener) override
Definition: sortdynres.cxx:132
virtual OUString SAL_CALL getImplementationName() override
Definition: sortdynres.cxx:85
virtual sal_Int16 SAL_CALL getCapabilities() override
Definition: sortdynres.cxx:213
#define DYNAMIC_RESULTSET_FACTORY_NAME
Definition: sortdynres.hxx:40
virtual void SAL_CALL dispose() override
Definition: sortdynres.cxx:102
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: sortdynres.cxx:512
int i
unsigned char sal_Bool
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: sortdynres.cxx:435
static osl::Mutex & getContainerMutex()
Definition: sortdynres.cxx:41
virtual OUString SAL_CALL getImplementationName() override
Definition: sortdynres.cxx:420
SortedDynamicResultSet(const css::uno::Reference< css::ucb::XDynamicResultSet > &xOriginal, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &aOptions, const css::uno::Reference< css::ucb::XAnyCompareFactory > &xCompFac, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: sortdynres.cxx:51
virtual void SAL_CALL notify(const css::ucb::ListEvent &Changes) override
Definition: sortdynres.cxx:524
void CheckProperties(sal_IntPtr nOldCount, bool bWasFinal)
static OUString getImplementationName_Static()
Definition: sortdynres.cxx:425
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &Listener) override
Definition: sortdynres.cxx:120
void ResortNew(EventList *pList)
Reference< XSingleServiceFactory > SAL_CALL createOneInstanceFactory(const Reference< XMultiServiceFactory > &rServiceManager, const OUString &rImplementationName, ComponentInstantiation pCreateFunction, const Sequence< OUString > &rServiceNames, rtl_ModuleCount *)
void Initialize(const css::uno::Sequence< css::ucb::NumberedSortingInfo > &xSortInfo, const css::uno::Reference< css::ucb::XAnyCompareFactory > &xCompFac)
virtual css::uno::Reference< css::ucb::XDynamicResultSet > SAL_CALL createSortedDynamicResultSet(const css::uno::Reference< css::ucb::XDynamicResultSet > &Source, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &Info, const css::uno::Reference< css::ucb::XAnyCompareFactory > &CompareFactory) override
Definition: sortdynres.cxx:470
void SetChanged(sal_IntPtr nPos, sal_IntPtr nCount)
static css::uno::Reference< css::uno::XInterface > SortedDynamicResultSetFactory_CreateInstance(const css::uno::Reference< css::lang::XMultiServiceFactory > &rSMgr)
Definition: sortdynres.cxx:442
SortedDynamicResultSetListener(SortedDynamicResultSet *mOwner)
Definition: sortdynres.cxx:498
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
Definition: sortresult.cxx:778
virtual ~SortedDynamicResultSetFactory() override
Definition: sortdynres.cxx:413
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: sortdynres.cxx:95
void Move(sal_IntPtr nPos, sal_IntPtr nCount, sal_IntPtr nOffset)
void InsertNew(sal_IntPtr nPos, sal_IntPtr nCount)
virtual void SAL_CALL connectToCache(const css::uno::Reference< css::ucb::XDynamicResultSet > &xCache) override
Definition: sortdynres.cxx:182
SortedDynamicResultSetFactory(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: sortdynres.cxx:406
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: sortdynres.cxx:90
sal_IntPtr GetCount() const
Definition: sortresult.hxx:149
const uno::Reference< uno::XComponentContext > m_xContext
static css::uno::Reference< css::lang::XSingleServiceFactory > createServiceFactory(const css::uno::Reference< css::lang::XMultiServiceFactory > &rxServiceMgr)
Definition: sortdynres.cxx:458
virtual void SAL_CALL setListener(const css::uno::Reference< css::ucb::XDynamicResultSetListener > &Listener) override
Definition: sortdynres.cxx:165