merge the formfield patch from ooo-build
[ooovba.git] / ucb / source / sorter / sortdynres.cxx
blobca498689bd8ecee754f7e3a77e700d208f884e24
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sortdynres.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 #include <vector>
35 #include <sortdynres.hxx>
36 #include <cppuhelper/interfacecontainer.hxx>
37 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
38 #include <com/sun/star/ucb/ListActionType.hpp>
39 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
40 #include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp>
41 #include <com/sun/star/ucb/XSourceInitialization.hpp>
43 //-----------------------------------------------------------------------------
44 using namespace com::sun::star::beans;
45 using namespace com::sun::star::lang;
46 using namespace com::sun::star::sdbc;
47 using namespace com::sun::star::ucb;
48 using namespace com::sun::star::uno;
49 using namespace cppu;
50 using namespace rtl;
52 //=========================================================================
54 // The mutex to synchronize access to containers.
55 static osl::Mutex& getContainerMutex()
57 static osl::Mutex* pMutex = NULL;
58 if( !pMutex )
60 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
61 if( !pMutex )
63 static osl::Mutex aMutex;
64 pMutex = &aMutex;
68 return *pMutex;
71 //=========================================================================
73 // SortedDynamicResultSet
75 //=========================================================================
77 SortedDynamicResultSet::SortedDynamicResultSet(
78 const Reference < XDynamicResultSet > &xOriginal,
79 const Sequence < NumberedSortingInfo > &aOptions,
80 const Reference < XAnyCompareFactory > &xCompFac,
81 const Reference < XMultiServiceFactory > &xSMgr )
83 mpDisposeEventListeners = NULL;
84 mpOwnListener = new SortedDynamicResultSetListener( this );
86 mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener );
88 mxOriginal = xOriginal;
89 maOptions = aOptions;
90 mxCompFac = xCompFac;
91 mxSMgr = xSMgr;
93 mpOne = NULL;
94 mpTwo = NULL;
96 mbGotWelcome = sal_False;
97 mbUseOne = sal_True;
98 mbStatic = sal_False;
101 //--------------------------------------------------------------------------
102 SortedDynamicResultSet::~SortedDynamicResultSet()
104 mpOwnListener->impl_OwnerDies();
105 mxOwnListener.clear();
107 delete mpDisposeEventListeners;
109 mxOne.clear();
110 mxTwo.clear();
111 mxOriginal.clear();
113 mpOne = NULL;
114 mpTwo = NULL;
117 //--------------------------------------------------------------------------
118 // XInterface methods.
119 //--------------------------------------------------------------------------
121 XINTERFACE_IMPL_4( SortedDynamicResultSet,
122 XTypeProvider,
123 XServiceInfo,
124 XComponent, /* base class of XDynamicResultSet */
125 XDynamicResultSet );
127 //--------------------------------------------------------------------------
128 // XTypeProvider methods.
129 //--------------------------------------------------------------------------
131 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet,
132 XTypeProvider,
133 XServiceInfo,
134 XDynamicResultSet );
136 //--------------------------------------------------------------------------
137 // XServiceInfo methods.
138 //--------------------------------------------------------------------------
140 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet,
141 OUString::createFromAscii(
142 "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
143 OUString::createFromAscii(
144 DYNAMIC_RESULTSET_SERVICE_NAME ) );
146 //--------------------------------------------------------------------------
147 // XComponent methods.
148 //--------------------------------------------------------------------------
149 void SAL_CALL SortedDynamicResultSet::dispose()
150 throw( RuntimeException )
152 osl::Guard< osl::Mutex > aGuard( maMutex );
154 if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() )
156 EventObject aEvt;
157 aEvt.Source = static_cast< XComponent * >( this );
158 mpDisposeEventListeners->disposeAndClear( aEvt );
161 mxOne.clear();
162 mxTwo.clear();
163 mxOriginal.clear();
165 mpOne = NULL;
166 mpTwo = NULL;
167 mbUseOne = sal_True;
170 //--------------------------------------------------------------------------
171 void SAL_CALL SortedDynamicResultSet::addEventListener(
172 const Reference< XEventListener >& Listener )
173 throw( RuntimeException )
175 osl::Guard< osl::Mutex > aGuard( maMutex );
177 if ( !mpDisposeEventListeners )
178 mpDisposeEventListeners =
179 new OInterfaceContainerHelper( getContainerMutex() );
181 mpDisposeEventListeners->addInterface( Listener );
184 //--------------------------------------------------------------------------
185 void SAL_CALL SortedDynamicResultSet::removeEventListener(
186 const Reference< XEventListener >& Listener )
187 throw( RuntimeException )
189 osl::Guard< osl::Mutex > aGuard( maMutex );
191 if ( mpDisposeEventListeners )
192 mpDisposeEventListeners->removeInterface( Listener );
195 //--------------------------------------------------------------------------
196 // XDynamicResultSet methods.
197 // ------------------------------------------------------------------------------
198 Reference< XResultSet > SAL_CALL
199 SortedDynamicResultSet::getStaticResultSet()
200 throw( ListenerAlreadySetException, RuntimeException )
202 osl::Guard< osl::Mutex > aGuard( maMutex );
204 if ( mxListener.is() )
205 throw ListenerAlreadySetException();
207 mbStatic = sal_True;
209 if ( mxOriginal.is() )
211 mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
212 mxOne = mpOne;
213 mpOne->Initialize( maOptions, mxCompFac );
216 return mxOne;
219 // ------------------------------------------------------------------------------
220 void SAL_CALL
221 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener )
222 throw( ListenerAlreadySetException, RuntimeException )
224 osl::Guard< osl::Mutex > aGuard( maMutex );
226 if ( mxListener.is() )
227 throw ListenerAlreadySetException();
229 addEventListener( Reference< XEventListener >::query( Listener ) );
231 mxListener = Listener;
233 if ( mxOriginal.is() )
234 mxOriginal->setListener( mxOwnListener );
237 // ------------------------------------------------------------------------------
238 void SAL_CALL
239 SortedDynamicResultSet::connectToCache(
240 const Reference< XDynamicResultSet > & xCache )
241 throw( ListenerAlreadySetException,
242 AlreadyInitializedException,
243 ServiceNotFoundException,
244 RuntimeException )
246 if( mxListener.is() )
247 throw ListenerAlreadySetException();
249 if( mbStatic )
250 throw ListenerAlreadySetException();
252 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
253 if( xTarget.is() && mxSMgr.is() )
255 Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
258 xStubFactory = Reference< XCachedDynamicResultSetStubFactory >(
259 mxSMgr->createInstance(
260 OUString::createFromAscii(
261 "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ),
262 UNO_QUERY );
264 catch ( Exception const & )
268 if( xStubFactory.is() )
270 xStubFactory->connectToCache(
271 this, xCache, Sequence< NumberedSortingInfo > (), NULL );
272 return;
275 throw ServiceNotFoundException();
278 // ------------------------------------------------------------------------------
279 sal_Int16 SAL_CALL
280 SortedDynamicResultSet::getCapabilities()
281 throw( RuntimeException )
283 osl::Guard< osl::Mutex > aGuard( maMutex );
285 sal_Int16 nCaps = 0;
287 if ( mxOriginal.is() )
288 nCaps = mxOriginal->getCapabilities();
290 nCaps |= ContentResultSetCapability::SORTED;
292 return nCaps;
295 //--------------------------------------------------------------------------
296 // XDynamicResultSetListener methods.
297 // ------------------------------------------------------------------------------
299 /** In the first notify-call the listener gets the two
300 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
301 are implementations of the service <type>ContentResultSet</type>.
303 <p>The notified new <type>XResultSet</type> will stay valid after returning
304 notification. The old one will become invalid after returning notification.
306 <p>While in notify-call the listener is allowed to read old and new version,
307 except in the first call, where only the new Resultset is valid.
309 <p>The Listener is allowed to blockade this call, until he really want to go
310 to the new version. The only situation, where the listener has to return the
311 update call at once is, while he disposes his broadcaster or while he is
312 removing himsef as listener (otherwise you deadlock)!!!
314 void SAL_CALL
315 SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
316 throw( RuntimeException )
318 osl::Guard< osl::Mutex > aGuard( maMutex );
320 sal_Bool bHasNew = sal_False;
321 sal_Bool bHasModified = sal_False;
323 SortedResultSet *pCurSet = NULL;
325 // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old
326 // nach New kopieren
327 if ( mbGotWelcome )
329 if ( mbUseOne )
331 mbUseOne = sal_False;
332 mpTwo->CopyData( mpOne );
333 pCurSet = mpTwo;
335 else
337 mbUseOne = sal_True;
338 mpOne->CopyData( mpTwo );
339 pCurSet = mpOne;
343 Any aRet;
345 try {
346 aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) );
348 catch ( UnknownPropertyException ) {}
349 catch ( WrappedTargetException ) {}
351 long nOldCount = pCurSet->GetCount();
352 sal_Bool bWasFinal = false;
354 aRet >>= bWasFinal;
356 // handle the actions in the list
357 for ( long i=0; i<Changes.Changes.getLength(); i++ )
359 const ListAction aAction = Changes.Changes[i];
360 switch ( aAction.ListActionType )
362 case ListActionType::WELCOME:
364 WelcomeDynamicResultSetStruct aWelcome;
365 if ( aAction.ActionInfo >>= aWelcome )
367 mpTwo = new SortedResultSet( aWelcome.Old );
368 mxTwo = mpTwo;
369 mpOne = new SortedResultSet( aWelcome.New );
370 mxOne = mpOne;
371 mpOne->Initialize( maOptions, mxCompFac );
372 mbGotWelcome = sal_True;
373 mbUseOne = sal_True;
374 pCurSet = mpOne;
376 aWelcome.Old = mxTwo;
377 aWelcome.New = mxOne;
379 ListAction *pWelcomeAction = new ListAction;
380 pWelcomeAction->ActionInfo <<= aWelcome;
381 pWelcomeAction->Position = 0;
382 pWelcomeAction->Count = 0;
383 pWelcomeAction->ListActionType = ListActionType::WELCOME;
385 maActions.Insert( pWelcomeAction );
387 else
389 // throw RuntimeException();
391 break;
393 case ListActionType::INSERTED:
395 pCurSet->InsertNew( aAction.Position, aAction.Count );
396 bHasNew = sal_True;
397 break;
399 case ListActionType::REMOVED:
401 pCurSet->Remove( aAction.Position,
402 aAction.Count,
403 &maActions );
404 break;
406 case ListActionType::MOVED:
408 long nOffset = 0;
409 if ( aAction.ActionInfo >>= nOffset )
411 pCurSet->Move( aAction.Position,
412 aAction.Count,
413 nOffset );
415 break;
417 case ListActionType::PROPERTIES_CHANGED:
419 pCurSet->SetChanged( aAction.Position, aAction.Count );
420 bHasModified = sal_True;
421 break;
423 default: break;
427 if ( bHasModified )
428 pCurSet->ResortModified( &maActions );
430 if ( bHasNew )
431 pCurSet->ResortNew( &maActions );
433 // send the new actions with a notify to the listeners
434 SendNotify();
436 // check for propertyChangeEvents
437 pCurSet->CheckProperties( nOldCount, bWasFinal );
440 //-----------------------------------------------------------------
441 // XEventListener
442 //-----------------------------------------------------------------
443 void SAL_CALL
444 SortedDynamicResultSet::impl_disposing( const EventObject& )
445 throw( RuntimeException )
447 mxListener.clear();
448 mxOriginal.clear();
451 // ------------------------------------------------------------------------------
452 // private methods
453 // ------------------------------------------------------------------------------
454 void SortedDynamicResultSet::SendNotify()
456 long nCount = maActions.Count();
458 if ( nCount && mxListener.is() )
460 Sequence< ListAction > aActionList( maActions.Count() );
461 ListAction *pActionList = aActionList.getArray();
463 for ( long i=0; i<nCount; i++ )
465 pActionList[ i ] = *(maActions.GetAction( i ));
468 ListEvent aNewEvent;
469 aNewEvent.Changes = aActionList;
471 mxListener->notify( aNewEvent );
474 // clean up
475 maActions.Clear();
478 //=========================================================================
480 // SortedDynamicResultSetFactory
482 //=========================================================================
483 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
484 const Reference< XMultiServiceFactory > & rSMgr )
486 mxSMgr = rSMgr;
489 //--------------------------------------------------------------------------
490 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
494 //--------------------------------------------------------------------------
495 // XInterface methods.
496 //--------------------------------------------------------------------------
498 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory,
499 XTypeProvider,
500 XServiceInfo,
501 XSortedDynamicResultSetFactory );
503 //--------------------------------------------------------------------------
504 // XTypeProvider methods.
505 //--------------------------------------------------------------------------
507 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory,
508 XTypeProvider,
509 XServiceInfo,
510 XSortedDynamicResultSetFactory );
512 //--------------------------------------------------------------------------
513 // XServiceInfo methods.
514 //--------------------------------------------------------------------------
516 XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory,
517 OUString::createFromAscii(
518 "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
519 OUString::createFromAscii(
520 DYNAMIC_RESULTSET_FACTORY_NAME ) );
522 //--------------------------------------------------------------------------
523 // Service factory implementation.
524 //--------------------------------------------------------------------------
526 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory );
528 //--------------------------------------------------------------------------
529 // SortedDynamicResultSetFactory methods.
530 //--------------------------------------------------------------------------
531 Reference< XDynamicResultSet > SAL_CALL
532 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
533 const Reference< XDynamicResultSet > & Source,
534 const Sequence< NumberedSortingInfo > & Info,
535 const Reference< XAnyCompareFactory > & CompareFactory )
536 throw( RuntimeException )
538 Reference< XDynamicResultSet > xRet;
539 xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr );
540 return xRet;
543 //=========================================================================
545 // EventList
547 //=========================================================================
549 void EventList::Clear()
551 for ( std::deque< LISTACTION* >::size_type i = 0;
552 i < maData.size(); ++i )
554 delete maData[i];
557 maData.clear();
560 //--------------------------------------------------------------------------
561 void EventList::AddEvent( long nType, long nPos, long nCount )
563 ListAction *pAction = new ListAction;
564 pAction->Position = nPos;
565 pAction->Count = nCount;
566 pAction->ListActionType = nType;
568 Insert( pAction );
571 //=================================================================
573 // SortedDynamicResultSetListener
575 //=================================================================
577 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
578 SortedDynamicResultSet *mOwner )
580 mpOwner = mOwner;
583 //-----------------------------------------------------------------
584 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
588 //-----------------------------------------------------------------
589 // XInterface methods.
590 //-----------------------------------------------------------------
592 XINTERFACE_IMPL_2( SortedDynamicResultSetListener,
593 XEventListener, /* base class of XDynamicResultSetListener */
594 XDynamicResultSetListener );
596 //-----------------------------------------------------------------
597 // XEventListener ( base of XDynamicResultSetListener )
598 //-----------------------------------------------------------------
599 void SAL_CALL
600 SortedDynamicResultSetListener::disposing( const EventObject& Source )
601 throw( RuntimeException )
603 osl::Guard< osl::Mutex > aGuard( maMutex );
605 if ( mpOwner )
606 mpOwner->impl_disposing( Source );
609 //-----------------------------------------------------------------
610 // XDynamicResultSetListener
611 //-----------------------------------------------------------------
612 void SAL_CALL
613 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
614 throw( RuntimeException )
616 osl::Guard< osl::Mutex > aGuard( maMutex );
618 if ( mpOwner )
619 mpOwner->impl_notify( Changes );
622 //-----------------------------------------------------------------
623 // own methods:
624 //-----------------------------------------------------------------
625 void SAL_CALL
626 SortedDynamicResultSetListener::impl_OwnerDies()
628 osl::Guard< osl::Mutex > aGuard( maMutex );
629 mpOwner = NULL;