Bump version to 24.04.3.4
[LibreOffice.git] / ucb / source / sorter / sortdynres.cxx
bloba3bf493a2ba083bfd5eb810bff5aea86442274ab
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sortdynres.hxx"
21 #include <cppuhelper/supportsservice.hxx>
22 #include <cppuhelper/weak.hxx>
23 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
24 #include <com/sun/star/ucb/ListActionType.hpp>
25 #include <com/sun/star/ucb/ListenerAlreadySetException.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 using namespace com::sun::star::beans;
32 using namespace com::sun::star::lang;
33 using namespace com::sun::star::sdbc;
34 using namespace com::sun::star::ucb;
35 using namespace com::sun::star::uno;
36 using namespace comphelper;
39 // SortedDynamicResultSet
41 SortedDynamicResultSet::SortedDynamicResultSet(
42 const Reference < XDynamicResultSet > &xOriginal,
43 const Sequence < NumberedSortingInfo > &aOptions,
44 const Reference < XAnyCompareFactory > &xCompFac,
45 const Reference < XComponentContext > &rxContext )
47 mxOwnListener = new SortedDynamicResultSetListener( this );
49 mxOriginal = xOriginal;
50 maOptions = aOptions;
51 mxCompFac = xCompFac;
52 m_xContext = rxContext;
54 mbGotWelcome = false;
55 mbUseOne = true;
56 mbStatic = false;
60 SortedDynamicResultSet::~SortedDynamicResultSet()
62 mxOwnListener->impl_OwnerDies();
63 mxOwnListener.clear();
66 std::unique_lock aGuard(maMutex);
67 maDisposeEventListeners.clear(aGuard);
70 mxOne.clear();
71 mxTwo.clear();
72 mxOriginal.clear();
75 // XServiceInfo methods.
77 OUString SAL_CALL SortedDynamicResultSet::getImplementationName()
79 return "com.sun.star.comp.ucb.SortedDynamicResultSet";
82 sal_Bool SAL_CALL SortedDynamicResultSet::supportsService( const OUString& ServiceName )
84 return cppu::supportsService( this, ServiceName );
87 css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSet::getSupportedServiceNames()
89 return { "com.sun.star.ucb.SortedDynamicResultSet" };
92 // XComponent methods.
94 void SAL_CALL SortedDynamicResultSet::dispose()
96 std::unique_lock aGuard( maMutex );
98 if ( maDisposeEventListeners.getLength(aGuard) )
100 EventObject aEvt;
101 aEvt.Source = static_cast< XComponent * >( this );
102 maDisposeEventListeners.disposeAndClear( aGuard, aEvt );
105 mxOne.clear();
106 mxTwo.clear();
107 mxOriginal.clear();
109 mbUseOne = true;
112 void SAL_CALL SortedDynamicResultSet::addEventListener(
113 const Reference< XEventListener >& Listener )
115 std::unique_lock aGuard( maMutex );
117 maDisposeEventListeners.addInterface( aGuard, Listener );
120 void SAL_CALL SortedDynamicResultSet::removeEventListener(
121 const Reference< XEventListener >& Listener )
123 std::unique_lock aGuard( maMutex );
125 maDisposeEventListeners.removeInterface( aGuard, Listener );
129 // XDynamicResultSet methods.
131 Reference< XResultSet > SAL_CALL
132 SortedDynamicResultSet::getStaticResultSet()
134 std::unique_lock aGuard( maMutex );
136 if ( mxListener.is() )
137 throw ListenerAlreadySetException();
139 mbStatic = true;
141 if ( mxOriginal.is() )
143 mxOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
144 mxOne->Initialize( maOptions, mxCompFac );
147 return mxOne;
151 void SAL_CALL
152 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener )
154 std::unique_lock aGuard( maMutex );
156 if ( mxListener.is() )
157 throw ListenerAlreadySetException();
159 maDisposeEventListeners.addInterface( aGuard, Listener );
161 mxListener = Listener;
163 if ( mxOriginal.is() )
164 mxOriginal->setListener( mxOwnListener );
168 void SAL_CALL
169 SortedDynamicResultSet::connectToCache( const Reference< XDynamicResultSet > & xCache )
171 if( mxListener.is() )
172 throw ListenerAlreadySetException();
174 if( mbStatic )
175 throw ListenerAlreadySetException();
177 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
178 if( xTarget.is() && m_xContext.is() )
180 Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
183 xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
185 catch ( Exception const & )
189 if( xStubFactory.is() )
191 xStubFactory->connectToCache(
192 this, xCache, Sequence< NumberedSortingInfo > (), nullptr );
193 return;
196 throw ServiceNotFoundException();
200 sal_Int16 SAL_CALL SortedDynamicResultSet::getCapabilities()
202 std::unique_lock aGuard( maMutex );
204 sal_Int16 nCaps = 0;
206 if ( mxOriginal.is() )
207 nCaps = mxOriginal->getCapabilities();
209 nCaps |= ContentResultSetCapability::SORTED;
211 return nCaps;
215 // XDynamicResultSetListener methods.
218 /** In the first notify-call the listener gets the two
219 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
220 are implementations of the service <type>ContentResultSet</type>.
222 <p>The notified new <type>XResultSet</type> will stay valid after returning
223 notification. The old one will become invalid after returning notification.
225 <p>While in notify-call the listener is allowed to read old and new version,
226 except in the first call, where only the new Resultset is valid.
228 <p>The Listener is allowed to blockade this call, until he really want to go
229 to the new version. The only situation, where the listener has to return the
230 update call at once is, while he disposes his broadcaster or while he is
231 removing himself as listener (otherwise you deadlock)!!!
233 void SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
235 std::unique_lock aGuard( maMutex );
237 bool bHasNew = false;
238 bool bHasModified = false;
240 SortedResultSet *pCurSet = nullptr;
242 // exchange mxNew and mxOld and immediately afterwards copy the tables
243 // from Old to New
244 if ( mbGotWelcome )
246 if ( mbUseOne )
248 mbUseOne = false;
249 mxTwo->CopyData( mxOne.get() );
250 pCurSet = mxTwo.get();
252 else
254 mbUseOne = true;
255 mxOne->CopyData( mxTwo.get() );
256 pCurSet = mxOne.get();
260 if (!pCurSet)
261 return;
263 Any aRet;
265 try {
266 aRet = pCurSet->getPropertyValue("IsRowCountFinal");
268 catch (const UnknownPropertyException&) {}
269 catch (const WrappedTargetException&) {}
271 sal_Int32 nOldCount = pCurSet->GetCount();
272 bool bWasFinal = false;
274 aRet >>= bWasFinal;
276 // handle the actions in the list
277 for ( const ListAction& aAction : Changes.Changes )
279 switch ( aAction.ListActionType )
281 case ListActionType::WELCOME:
283 WelcomeDynamicResultSetStruct aWelcome;
284 if ( aAction.ActionInfo >>= aWelcome )
286 mxTwo = new SortedResultSet( aWelcome.Old );
287 mxOne = new SortedResultSet( aWelcome.New );
288 mxOne->Initialize( maOptions, mxCompFac );
289 mbGotWelcome = true;
290 mbUseOne = true;
291 pCurSet = mxOne.get();
293 aWelcome.Old = mxTwo.get();
294 aWelcome.New = mxOne.get();
296 ListAction aWelcomeAction;
297 aWelcomeAction.ActionInfo <<= aWelcome;
298 aWelcomeAction.Position = 0;
299 aWelcomeAction.Count = 0;
300 aWelcomeAction.ListActionType = ListActionType::WELCOME;
302 maActions.Insert( aWelcomeAction );
304 else
306 // throw RuntimeException();
308 break;
310 case ListActionType::INSERTED:
312 pCurSet->InsertNew( aAction.Position, aAction.Count );
313 bHasNew = true;
314 break;
316 case ListActionType::REMOVED:
318 pCurSet->Remove( aAction.Position,
319 aAction.Count,
320 &maActions );
321 break;
323 case ListActionType::MOVED:
325 sal_Int32 nOffset = 0;
326 if ( aAction.ActionInfo >>= nOffset )
328 pCurSet->Move( aAction.Position,
329 aAction.Count,
330 nOffset );
332 break;
334 case ListActionType::PROPERTIES_CHANGED:
336 pCurSet->SetChanged( aAction.Position, aAction.Count );
337 bHasModified = true;
338 break;
340 default: break;
344 if ( bHasModified )
345 pCurSet->ResortModified( &maActions );
347 if ( bHasNew )
348 pCurSet->ResortNew( &maActions );
350 // send the new actions with a notify to the listeners
351 SendNotify();
353 // check for propertyChangeEvents
354 pCurSet->CheckProperties( nOldCount, bWasFinal );
357 // XEventListener
359 void SortedDynamicResultSet::impl_disposing()
361 mxListener.clear();
362 mxOriginal.clear();
365 // private methods
367 void SortedDynamicResultSet::SendNotify()
369 sal_Int32 nCount = maActions.Count();
371 if ( nCount && mxListener.is() )
373 Sequence< ListAction > aActionList( maActions.Count() );
374 ListAction *pActionList = aActionList.getArray();
376 for ( sal_Int32 i=0; i<nCount; i++ )
378 pActionList[ i ] = maActions.GetAction( i );
381 ListEvent aNewEvent;
382 aNewEvent.Changes = aActionList;
384 mxListener->notify( aNewEvent );
387 // clean up
388 maActions.Clear();
391 // SortedDynamicResultSetFactory
393 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
394 const Reference< XComponentContext > & rxContext )
396 m_xContext = rxContext;
400 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
405 // XServiceInfo methods.
407 OUString SAL_CALL SortedDynamicResultSetFactory::getImplementationName()
409 return "com.sun.star.comp.ucb.SortedDynamicResultSetFactory";
412 sal_Bool SAL_CALL SortedDynamicResultSetFactory::supportsService( const OUString& ServiceName )
414 return cppu::supportsService( this, ServiceName );
417 css::uno::Sequence< OUString > SAL_CALL SortedDynamicResultSetFactory::getSupportedServiceNames()
419 return { "com.sun.star.ucb.SortedDynamicResultSetFactory" };
423 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
424 ucb_SortedDynamicResultSetFactory_get_implementation(
425 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
427 return cppu::acquire(new SortedDynamicResultSetFactory(context));
430 // SortedDynamicResultSetFactory methods.
432 Reference< XDynamicResultSet > SAL_CALL
433 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
434 const Reference< XDynamicResultSet > & Source,
435 const Sequence< NumberedSortingInfo > & Info,
436 const Reference< XAnyCompareFactory > & CompareFactory )
438 Reference< XDynamicResultSet > xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, m_xContext );
439 return xRet;
442 // EventList
444 void EventList::Clear()
446 maData.clear();
449 void EventList::AddEvent( sal_IntPtr nType, sal_Int32 nPos )
451 ListAction aAction;
452 aAction.Position = nPos;
453 aAction.Count = 1;
454 aAction.ListActionType = nType;
456 Insert( aAction );
459 // SortedDynamicResultSetListener
461 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
462 SortedDynamicResultSet *mOwner )
464 mpOwner = mOwner;
468 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
472 // XEventListener ( base of XDynamicResultSetListener )
474 void SAL_CALL
475 SortedDynamicResultSetListener::disposing( const EventObject& /*Source*/ )
477 std::unique_lock aGuard( maMutex );
479 if ( mpOwner )
480 mpOwner->impl_disposing();
484 // XDynamicResultSetListener
486 void SAL_CALL
487 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
489 std::unique_lock aGuard( maMutex );
491 if ( mpOwner )
492 mpOwner->impl_notify( Changes );
495 // own methods:
497 void
498 SortedDynamicResultSetListener::impl_OwnerDies()
500 std::unique_lock aGuard( maMutex );
501 mpOwner = nullptr;
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */