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 "sortdynres.hxx"
23 #include <cppuhelper/weak.hxx>
24 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/ListenerAlreadySetException.hpp>
27 #include <com/sun/star/ucb/ServiceNotFoundException.hpp>
28 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
29 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
30 #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 {
97  return { "com.sun.star.ucb.SortedDynamicResultSet" };
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;
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( Listener );
173 
174  mxListener = Listener;
175 
176  if ( mxOriginal.is() )
177  mxOriginal->setListener( mxOwnListener );
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  sal_Int32 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  ListAction aWelcomeAction;
310  aWelcomeAction.ActionInfo <<= aWelcome;
311  aWelcomeAction.Position = 0;
312  aWelcomeAction.Count = 0;
313  aWelcomeAction.ListActionType = ListActionType::WELCOME;
314 
315  maActions.Insert( aWelcomeAction );
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  sal_Int32 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 "com.sun.star.comp.ucb.SortedDynamicResultSetFactory";
423 }
424 
425 sal_Bool SAL_CALL SortedDynamicResultSetFactory::supportsService( const OUString& ServiceName )
426 {
427  return cppu::supportsService( this, ServiceName );
428 }
429 
430 css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSetFactory::getSupportedServiceNames()
431 {
432  return { "com.sun.star.ucb.SortedDynamicResultSetFactory" };
433 }
434 
435 
436 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
438  css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
439 {
440  return cppu::acquire(new SortedDynamicResultSetFactory(context));
441 }
442 
443 // SortedDynamicResultSetFactory methods.
444 
447  const Reference< XDynamicResultSet > & Source,
448  const Sequence< NumberedSortingInfo > & Info,
449  const Reference< XAnyCompareFactory > & CompareFactory )
450 {
451  Reference< XDynamicResultSet > xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, m_xContext );
452  return xRet;
453 }
454 
455 // EventList
456 
458 {
459  maData.clear();
460 }
461 
462 void EventList::AddEvent( sal_IntPtr nType, sal_Int32 nPos )
463 {
464  ListAction aAction;
465  aAction.Position = nPos;
466  aAction.Count = 1;
467  aAction.ListActionType = nType;
468 
469  Insert( aAction );
470 }
471 
472 // SortedDynamicResultSetListener
473 
475  SortedDynamicResultSet *mOwner )
476 {
477  mpOwner = mOwner;
478 }
479 
480 
482 {
483 }
484 
485 // XEventListener ( base of XDynamicResultSetListener )
486 
487 void SAL_CALL
488 SortedDynamicResultSetListener::disposing( const EventObject& /*Source*/ )
489 {
490  osl::Guard< osl::Mutex > aGuard( maMutex );
491 
492  if ( mpOwner )
493  mpOwner->impl_disposing();
494 }
495 
496 
497 // XDynamicResultSetListener
498 
499 void SAL_CALL
500 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
501 {
502  osl::Guard< osl::Mutex > aGuard( maMutex );
503 
504  if ( mpOwner )
505  mpOwner->impl_notify( Changes );
506 }
507 
508 // own methods:
509 
510 void
512 {
513  osl::Guard< osl::Mutex > aGuard( maMutex );
514  mpOwner = nullptr;
515 }
516 
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ResortModified(EventList *pList)
Reference< XInterface > xTarget
std::mutex maMutex
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
std::vector< sal_Int8 > maData
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: sortdynres.cxx:425
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * ucb_SortedDynamicResultSetFactory_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: sortdynres.cxx:437
void AddEvent(sal_IntPtr nType, sal_Int32 nPos)
Definition: sortdynres.cxx:462
int nCount
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void CopyData(SortedResultSet *pSource)
virtual ~SortedDynamicResultSetListener() override
Definition: sortdynres.cxx:481
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:457
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
sal_Int32 GetCount() const
Definition: sortresult.hxx:143
virtual sal_Int16 SAL_CALL getCapabilities() override
Definition: sortdynres.cxx:213
int i
virtual void SAL_CALL dispose() override
Definition: sortdynres.cxx:102
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: sortdynres.cxx:488
unsigned char sal_Bool
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: sortdynres.cxx:430
void Move(sal_Int32 nPos, sal_Int32 nCount, sal_Int32 nOffset)
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:500
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &Listener) override
Definition: sortdynres.cxx:120
void ResortNew(EventList *pList)
void Remove(sal_Int32 nPos, sal_Int32 nCount, EventList *pList)
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:446
Reference< script::XScriptListener > mxListener
void SetChanged(sal_Int32 nPos, sal_Int32 nCount)
SortedDynamicResultSetListener(SortedDynamicResultSet *mOwner)
Definition: sortdynres.cxx:474
void CheckProperties(sal_Int32 nOldCount, bool bWasFinal)
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
Definition: sortresult.cxx:765
virtual ~SortedDynamicResultSetFactory() override
Definition: sortdynres.cxx:413
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: sortdynres.cxx:95
virtual void SAL_CALL connectToCache(const css::uno::Reference< css::ucb::XDynamicResultSet > &xCache) override
Definition: sortdynres.cxx:182
void InsertNew(sal_Int32 nPos, sal_Int32 nCount)
SortedDynamicResultSetFactory(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: sortdynres.cxx:406
Reference< XComponentContext > m_xContext
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: sortdynres.cxx:90
virtual void Insert(SotClipboardFormatId nFormat, const OUString &rFormatName) override
virtual void SAL_CALL setListener(const css::uno::Reference< css::ucb::XDynamicResultSetListener > &Listener) override
Definition: sortdynres.cxx:165