bump product version to 4.1.6.2
[LibreOffice.git] / ucb / source / sorter / sortdynres.cxx
blobd73f9b26356f02eac4e2a132f3c3467594d7d622
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 .
21 #include <vector>
22 #include <sortdynres.hxx>
23 #include <cppuhelper/interfacecontainer.hxx>
24 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
27 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
28 #include <com/sun/star/ucb/XSourceInitialization.hpp>
30 //-----------------------------------------------------------------------------
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 cppu;
39 //=========================================================================
41 // The mutex to synchronize access to containers.
42 static osl::Mutex& getContainerMutex()
44 static osl::Mutex* pMutex = NULL;
45 if( !pMutex )
47 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
48 if( !pMutex )
50 static osl::Mutex aMutex;
51 pMutex = &aMutex;
55 return *pMutex;
58 //=========================================================================
60 // SortedDynamicResultSet
62 //=========================================================================
64 SortedDynamicResultSet::SortedDynamicResultSet(
65 const Reference < XDynamicResultSet > &xOriginal,
66 const Sequence < NumberedSortingInfo > &aOptions,
67 const Reference < XAnyCompareFactory > &xCompFac,
68 const Reference < XComponentContext > &rxContext )
70 mpDisposeEventListeners = NULL;
71 mpOwnListener = new SortedDynamicResultSetListener( this );
73 mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener );
75 mxOriginal = xOriginal;
76 maOptions = aOptions;
77 mxCompFac = xCompFac;
78 m_xContext = rxContext;
80 mpOne = NULL;
81 mpTwo = NULL;
83 mbGotWelcome = sal_False;
84 mbUseOne = sal_True;
85 mbStatic = sal_False;
88 //--------------------------------------------------------------------------
89 SortedDynamicResultSet::~SortedDynamicResultSet()
91 mpOwnListener->impl_OwnerDies();
92 mxOwnListener.clear();
94 delete mpDisposeEventListeners;
96 mxOne.clear();
97 mxTwo.clear();
98 mxOriginal.clear();
100 mpOne = NULL;
101 mpTwo = NULL;
104 //--------------------------------------------------------------------------
105 // XInterface methods.
106 //--------------------------------------------------------------------------
108 XINTERFACE_IMPL_4( SortedDynamicResultSet,
109 XTypeProvider,
110 XServiceInfo,
111 XComponent, /* base class of XDynamicResultSet */
112 XDynamicResultSet );
114 //--------------------------------------------------------------------------
115 // XTypeProvider methods.
116 //--------------------------------------------------------------------------
118 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet,
119 XTypeProvider,
120 XServiceInfo,
121 XDynamicResultSet );
123 //--------------------------------------------------------------------------
124 // XServiceInfo methods.
125 //--------------------------------------------------------------------------
127 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet,
128 OUString( "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
129 OUString( DYNAMIC_RESULTSET_SERVICE_NAME ) );
131 //--------------------------------------------------------------------------
132 // XComponent methods.
133 //--------------------------------------------------------------------------
134 void SAL_CALL SortedDynamicResultSet::dispose()
135 throw( RuntimeException )
137 osl::Guard< osl::Mutex > aGuard( maMutex );
139 if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() )
141 EventObject aEvt;
142 aEvt.Source = static_cast< XComponent * >( this );
143 mpDisposeEventListeners->disposeAndClear( aEvt );
146 mxOne.clear();
147 mxTwo.clear();
148 mxOriginal.clear();
150 mpOne = NULL;
151 mpTwo = NULL;
152 mbUseOne = sal_True;
155 //--------------------------------------------------------------------------
156 void SAL_CALL SortedDynamicResultSet::addEventListener(
157 const Reference< XEventListener >& Listener )
158 throw( RuntimeException )
160 osl::Guard< osl::Mutex > aGuard( maMutex );
162 if ( !mpDisposeEventListeners )
163 mpDisposeEventListeners =
164 new OInterfaceContainerHelper( getContainerMutex() );
166 mpDisposeEventListeners->addInterface( Listener );
169 //--------------------------------------------------------------------------
170 void SAL_CALL SortedDynamicResultSet::removeEventListener(
171 const Reference< XEventListener >& Listener )
172 throw( RuntimeException )
174 osl::Guard< osl::Mutex > aGuard( maMutex );
176 if ( mpDisposeEventListeners )
177 mpDisposeEventListeners->removeInterface( Listener );
180 //--------------------------------------------------------------------------
181 // XDynamicResultSet methods.
182 // ------------------------------------------------------------------------------
183 Reference< XResultSet > SAL_CALL
184 SortedDynamicResultSet::getStaticResultSet()
185 throw( ListenerAlreadySetException, RuntimeException )
187 osl::Guard< osl::Mutex > aGuard( maMutex );
189 if ( mxListener.is() )
190 throw ListenerAlreadySetException();
192 mbStatic = sal_True;
194 if ( mxOriginal.is() )
196 mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
197 mxOne = mpOne;
198 mpOne->Initialize( maOptions, mxCompFac );
201 return mxOne;
204 // ------------------------------------------------------------------------------
205 void SAL_CALL
206 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener )
207 throw( ListenerAlreadySetException, RuntimeException )
209 osl::Guard< osl::Mutex > aGuard( maMutex );
211 if ( mxListener.is() )
212 throw ListenerAlreadySetException();
214 addEventListener( Reference< XEventListener >::query( Listener ) );
216 mxListener = Listener;
218 if ( mxOriginal.is() )
219 mxOriginal->setListener( mxOwnListener );
222 // ------------------------------------------------------------------------------
223 void SAL_CALL
224 SortedDynamicResultSet::connectToCache(
225 const Reference< XDynamicResultSet > & xCache )
226 throw( ListenerAlreadySetException,
227 AlreadyInitializedException,
228 ServiceNotFoundException,
229 RuntimeException )
231 if( mxListener.is() )
232 throw ListenerAlreadySetException();
234 if( mbStatic )
235 throw ListenerAlreadySetException();
237 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
238 if( xTarget.is() && m_xContext.is() )
240 Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
243 xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
245 catch ( Exception const & )
249 if( xStubFactory.is() )
251 xStubFactory->connectToCache(
252 this, xCache, Sequence< NumberedSortingInfo > (), NULL );
253 return;
256 throw ServiceNotFoundException();
259 // ------------------------------------------------------------------------------
260 sal_Int16 SAL_CALL
261 SortedDynamicResultSet::getCapabilities()
262 throw( RuntimeException )
264 osl::Guard< osl::Mutex > aGuard( maMutex );
266 sal_Int16 nCaps = 0;
268 if ( mxOriginal.is() )
269 nCaps = mxOriginal->getCapabilities();
271 nCaps |= ContentResultSetCapability::SORTED;
273 return nCaps;
276 //--------------------------------------------------------------------------
277 // XDynamicResultSetListener methods.
278 // ------------------------------------------------------------------------------
280 /** In the first notify-call the listener gets the two
281 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
282 are implementations of the service <type>ContentResultSet</type>.
284 <p>The notified new <type>XResultSet</type> will stay valid after returning
285 notification. The old one will become invalid after returning notification.
287 <p>While in notify-call the listener is allowed to read old and new version,
288 except in the first call, where only the new Resultset is valid.
290 <p>The Listener is allowed to blockade this call, until he really want to go
291 to the new version. The only situation, where the listener has to return the
292 update call at once is, while he disposes his broadcaster or while he is
293 removing himsef as listener (otherwise you deadlock)!!!
295 void SAL_CALL
296 SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
297 throw( RuntimeException )
299 osl::Guard< osl::Mutex > aGuard( maMutex );
301 sal_Bool bHasNew = sal_False;
302 sal_Bool bHasModified = sal_False;
304 SortedResultSet *pCurSet = NULL;
306 // exchange mxNew and mxOld and immediately afterwards copy the tables
307 // from Old to New
308 if ( mbGotWelcome )
310 if ( mbUseOne )
312 mbUseOne = sal_False;
313 mpTwo->CopyData( mpOne );
314 pCurSet = mpTwo;
316 else
318 mbUseOne = sal_True;
319 mpOne->CopyData( mpTwo );
320 pCurSet = mpOne;
324 Any aRet;
326 try {
327 aRet = pCurSet->getPropertyValue( OUString("IsRowCountFinal") );
329 catch (const UnknownPropertyException&) {}
330 catch (const WrappedTargetException&) {}
332 long nOldCount = pCurSet->GetCount();
333 sal_Bool bWasFinal = false;
335 aRet >>= bWasFinal;
337 // handle the actions in the list
338 for ( long i=0; i<Changes.Changes.getLength(); i++ )
340 const ListAction aAction = Changes.Changes[i];
341 switch ( aAction.ListActionType )
343 case ListActionType::WELCOME:
345 WelcomeDynamicResultSetStruct aWelcome;
346 if ( aAction.ActionInfo >>= aWelcome )
348 mpTwo = new SortedResultSet( aWelcome.Old );
349 mxTwo = mpTwo;
350 mpOne = new SortedResultSet( aWelcome.New );
351 mxOne = mpOne;
352 mpOne->Initialize( maOptions, mxCompFac );
353 mbGotWelcome = sal_True;
354 mbUseOne = sal_True;
355 pCurSet = mpOne;
357 aWelcome.Old = mxTwo;
358 aWelcome.New = mxOne;
360 ListAction *pWelcomeAction = new ListAction;
361 pWelcomeAction->ActionInfo <<= aWelcome;
362 pWelcomeAction->Position = 0;
363 pWelcomeAction->Count = 0;
364 pWelcomeAction->ListActionType = ListActionType::WELCOME;
366 maActions.Insert( pWelcomeAction );
368 else
370 // throw RuntimeException();
372 break;
374 case ListActionType::INSERTED:
376 pCurSet->InsertNew( aAction.Position, aAction.Count );
377 bHasNew = sal_True;
378 break;
380 case ListActionType::REMOVED:
382 pCurSet->Remove( aAction.Position,
383 aAction.Count,
384 &maActions );
385 break;
387 case ListActionType::MOVED:
389 long nOffset = 0;
390 if ( aAction.ActionInfo >>= nOffset )
392 pCurSet->Move( aAction.Position,
393 aAction.Count,
394 nOffset );
396 break;
398 case ListActionType::PROPERTIES_CHANGED:
400 pCurSet->SetChanged( aAction.Position, aAction.Count );
401 bHasModified = sal_True;
402 break;
404 default: break;
408 if ( bHasModified )
409 pCurSet->ResortModified( &maActions );
411 if ( bHasNew )
412 pCurSet->ResortNew( &maActions );
414 // send the new actions with a notify to the listeners
415 SendNotify();
417 // check for propertyChangeEvents
418 pCurSet->CheckProperties( nOldCount, bWasFinal );
421 //-----------------------------------------------------------------
422 // XEventListener
423 //-----------------------------------------------------------------
424 void SAL_CALL
425 SortedDynamicResultSet::impl_disposing( const EventObject& )
426 throw( RuntimeException )
428 mxListener.clear();
429 mxOriginal.clear();
432 // ------------------------------------------------------------------------------
433 // private methods
434 // ------------------------------------------------------------------------------
435 void SortedDynamicResultSet::SendNotify()
437 long nCount = maActions.Count();
439 if ( nCount && mxListener.is() )
441 Sequence< ListAction > aActionList( maActions.Count() );
442 ListAction *pActionList = aActionList.getArray();
444 for ( long i=0; i<nCount; i++ )
446 pActionList[ i ] = *(maActions.GetAction( i ));
449 ListEvent aNewEvent;
450 aNewEvent.Changes = aActionList;
452 mxListener->notify( aNewEvent );
455 // clean up
456 maActions.Clear();
459 //=========================================================================
461 // SortedDynamicResultSetFactory
463 //=========================================================================
464 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
465 const Reference< XComponentContext > & rxContext )
467 m_xContext = rxContext;
470 //--------------------------------------------------------------------------
471 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
475 //--------------------------------------------------------------------------
476 // XInterface methods.
477 //--------------------------------------------------------------------------
479 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory,
480 XTypeProvider,
481 XServiceInfo,
482 XSortedDynamicResultSetFactory );
484 //--------------------------------------------------------------------------
485 // XTypeProvider methods.
486 //--------------------------------------------------------------------------
488 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory,
489 XTypeProvider,
490 XServiceInfo,
491 XSortedDynamicResultSetFactory );
493 //--------------------------------------------------------------------------
494 // XServiceInfo methods.
495 //--------------------------------------------------------------------------
497 XSERVICEINFO_IMPL_1_CTX( SortedDynamicResultSetFactory,
498 OUString( "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
499 OUString( DYNAMIC_RESULTSET_FACTORY_NAME ) );
501 //--------------------------------------------------------------------------
502 // Service factory implementation.
503 //--------------------------------------------------------------------------
505 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory );
507 //--------------------------------------------------------------------------
508 // SortedDynamicResultSetFactory methods.
509 //--------------------------------------------------------------------------
510 Reference< XDynamicResultSet > SAL_CALL
511 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
512 const Reference< XDynamicResultSet > & Source,
513 const Sequence< NumberedSortingInfo > & Info,
514 const Reference< XAnyCompareFactory > & CompareFactory )
515 throw( RuntimeException )
517 Reference< XDynamicResultSet > xRet;
518 xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, m_xContext );
519 return xRet;
522 //=========================================================================
524 // EventList
526 //=========================================================================
528 void EventList::Clear()
530 for ( std::deque< ListAction* >::size_type i = 0;
531 i < maData.size(); ++i )
533 delete maData[i];
536 maData.clear();
539 //--------------------------------------------------------------------------
540 void EventList::AddEvent( long nType, long nPos, long nCount )
542 ListAction *pAction = new ListAction;
543 pAction->Position = nPos;
544 pAction->Count = nCount;
545 pAction->ListActionType = nType;
547 Insert( pAction );
550 //=================================================================
552 // SortedDynamicResultSetListener
554 //=================================================================
556 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
557 SortedDynamicResultSet *mOwner )
559 mpOwner = mOwner;
562 //-----------------------------------------------------------------
563 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
567 //-----------------------------------------------------------------
568 // XInterface methods.
569 //-----------------------------------------------------------------
571 XINTERFACE_IMPL_2( SortedDynamicResultSetListener,
572 XEventListener, /* base class of XDynamicResultSetListener */
573 XDynamicResultSetListener );
575 //-----------------------------------------------------------------
576 // XEventListener ( base of XDynamicResultSetListener )
577 //-----------------------------------------------------------------
578 void SAL_CALL
579 SortedDynamicResultSetListener::disposing( const EventObject& Source )
580 throw( RuntimeException )
582 osl::Guard< osl::Mutex > aGuard( maMutex );
584 if ( mpOwner )
585 mpOwner->impl_disposing( Source );
588 //-----------------------------------------------------------------
589 // XDynamicResultSetListener
590 //-----------------------------------------------------------------
591 void SAL_CALL
592 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
593 throw( RuntimeException )
595 osl::Guard< osl::Mutex > aGuard( maMutex );
597 if ( mpOwner )
598 mpOwner->impl_notify( Changes );
601 //-----------------------------------------------------------------
602 // own methods:
603 //-----------------------------------------------------------------
604 void SAL_CALL
605 SortedDynamicResultSetListener::impl_OwnerDies()
607 osl::Guard< osl::Mutex > aGuard( maMutex );
608 mpOwner = NULL;
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */